Tor 0.4.9.0-alpha-dev
namemap.c
Go to the documentation of this file.
1/* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4/* See LICENSE for licensing information */
5
6/**
7 * @file namemap.c
8 * @brief Mappings between identifiers and 16-bit ints.
9 **/
10
11#include "orconfig.h"
15#include "lib/log/util_bug.h"
16#include "lib/malloc/malloc.h"
17#include "lib/string/printf.h"
18
19#include "ext/siphash.h"
20
21#include <string.h>
22
23/** Helper for namemap hashtable implementation: compare two entries. */
24static inline int
26{
27 return !strcmp(a->name, b->name);
28}
29
30/** Helper for namemap hashtable implementation: hash an entry. */
31static inline unsigned
33{
34 return (unsigned) siphash24g(a->name, strlen(a->name));
35}
36
39HT_GENERATE2(namemap_ht, mapped_name_t, node, mapped_name_hash,
41
42/** Set up an uninitialized <b>map</b>. */
43void
45{
46 memset(map, 0, sizeof(*map));
47 HT_INIT(namemap_ht, &map->ht);
48 map->names = smartlist_new();
49}
50
51/** Return the name that <b>map</b> associates with a given <b>id</b>, or
52 * NULL if there is no such name. */
53const char *
54namemap_get_name(const namemap_t *map, unsigned id)
55{
56 if (map->names && id < (unsigned)smartlist_len(map->names)) {
57 mapped_name_t *name = smartlist_get(map->names, (int)id);
58 return name->name;
59 } else {
60 return NULL;
61 }
62}
63
64/**
65 * Return the name that <b>map</b> associates with a given <b>id</b>, or a
66 * pointer to a statically allocated string describing the value of <b>id</b>
67 * if no such name exists.
68 **/
69const char *
70namemap_fmt_name(const namemap_t *map, unsigned id)
71{
72 static char buf[32];
73
74 const char *name = namemap_get_name(map, id);
75 if (name)
76 return name;
77
78 tor_snprintf(buf, sizeof(buf), "{%u}", id);
79
80 return buf;
81}
82
83/**
84 * Helper: As namemap_get_id(), but requires that <b>name</b> is
85 * <b>namelen</b> characters long, and that <b>namelen</b> is no more than
86 * MAX_NAMEMAP_NAME_LEN.
87 */
88static unsigned
90 const char *name,
91 size_t namelen)
92{
93 union {
95 char storage[MAX_NAMEMAP_NAME_LEN + sizeof(mapped_name_t) + 1];
96 } u;
97 memcpy(u.n.name, name, namelen);
98 u.n.name[namelen] = 0;
99 const mapped_name_t *found = HT_FIND(namemap_ht, &map->ht, &u.n);
100 if (found) {
101 tor_assert(map->names);
102 tor_assert(smartlist_get(map->names, found->intval) == found);
103 return found->intval;
104 }
105
106 return NAMEMAP_ERR;
107}
108
109/**
110 * Return the identifier currently associated by <b>map</b> with the name
111 * <b>name</b>, or NAMEMAP_ERR if no such identifier exists.
112 **/
113unsigned
115 const char *name)
116{
117 size_t namelen = strlen(name);
118 if (namelen > MAX_NAMEMAP_NAME_LEN) {
119 return NAMEMAP_ERR;
120 }
121
122 return namemap_get_id_unchecked(map, name, namelen);
123}
124
125/**
126 * Return the identifier associated by <b>map</b> with the name
127 * <b>name</b>, allocating a new identifier in <b>map</b> if none exists.
128 *
129 * Return NAMEMAP_ERR if <b>name</b> is too long, or if there are no more
130 * identifiers we can allocate.
131 **/
132unsigned
134 const char *name)
135{
136 size_t namelen = strlen(name);
137 if (namelen > MAX_NAMEMAP_NAME_LEN) {
138 return NAMEMAP_ERR;
139 }
140
141 if (PREDICT_UNLIKELY(map->names == NULL))
142 map->names = smartlist_new();
143
144 unsigned found = namemap_get_id_unchecked(map, name, namelen);
145 if (found != NAMEMAP_ERR)
146 return found;
147
148 unsigned new_id = (unsigned)smartlist_len(map->names);
149 if (new_id == NAMEMAP_ERR)
150 return NAMEMAP_ERR; /* Can't allocate any more. */
151
152 mapped_name_t *insert = tor_malloc_zero(
153 offsetof(mapped_name_t, name) + namelen + 1);
154 memcpy(insert->name, name, namelen+1);
155 insert->intval = new_id;
156
157 HT_INSERT(namemap_ht, &map->ht, insert);
158 smartlist_add(map->names, insert);
159
160 return new_id;
161}
162
163/** Return the number of entries in 'names' */
164size_t
166{
167 if (PREDICT_UNLIKELY(map->names == NULL))
168 return 0;
169
170 return smartlist_len(map->names);
171}
172
173/**
174 * Release all storage held in <b>map</b>.
175 */
176void
178{
179 if (!map)
180 return;
181
182 HT_CLEAR(namemap_ht, &map->ht);
183 if (map->names) {
184 SMARTLIST_FOREACH(map->names, mapped_name_t *, n,
185 tor_free(n));
186 smartlist_free(map->names);
187 }
188 memset(map, 0, sizeof(*map));
189}
const char * name
Definition: config.c:2462
HT_PROTOTYPE(hs_circuitmap_ht, circuit_t, hs_circuitmap_node, hs_circuit_hash_token, hs_circuits_have_same_token)
void * tor_reallocarray_(void *ptr, size_t sz1, size_t sz2)
Definition: malloc.c:146
void tor_free_(void *mem)
Definition: malloc.c:227
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:56
unsigned namemap_get_id(const namemap_t *map, const char *name)
Definition: namemap.c:114
size_t namemap_get_size(const namemap_t *map)
Definition: namemap.c:165
static unsigned namemap_get_id_unchecked(const namemap_t *map, const char *name, size_t namelen)
Definition: namemap.c:89
const char * namemap_fmt_name(const namemap_t *map, unsigned id)
Definition: namemap.c:70
void namemap_init(namemap_t *map)
Definition: namemap.c:44
static unsigned mapped_name_hash(const mapped_name_t *a)
Definition: namemap.c:32
void namemap_clear(namemap_t *map)
Definition: namemap.c:177
static int mapped_name_eq(const mapped_name_t *a, const mapped_name_t *b)
Definition: namemap.c:25
unsigned namemap_get_or_create_id(namemap_t *map, const char *name)
Definition: namemap.c:133
const char * namemap_get_name(const namemap_t *map, unsigned id)
Definition: namemap.c:54
Header for namemap.c.
#define NAMEMAP_ERR
Definition: namemap.h:23
Internal declarations for namemap structure.
#define MAX_NAMEMAP_NAME_LEN
Definition: namemap_st.h:20
int tor_snprintf(char *str, size_t size, const char *format,...)
Definition: printf.c:27
Header for printf.c.
Header for smartlist.c.
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103