"Fossies" - the Fresh Open Source Software Archive

Member "tor-0.4.1.6/src/lib/container/namemap.c" (10 Jun 2019, 4745 Bytes) of package /linux/misc/tor-0.4.1.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "namemap.c" see the Fossies "Dox" file reference documentation.

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