"Fossies" - the Fresh Open Source Software Archive

Member "tor-0.4.1.6/src/lib/dispatch/dispatch_new.c" (10 Jun 2019, 5204 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 "dispatch_new.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.4.1.6_vs_0.4.2.4-rc.

    1 /* Copyright (c) 2001, Matej Pfajfar.
    2  * Copyright (c) 2001-2004, Roger Dingledine.
    3  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
    4  * Copyright (c) 2007-2018, The Tor Project, Inc. */
    5 /* See LICENSE for licensing information */
    6 
    7 /**
    8  * \file dispatch_new.c
    9  * \brief Code to construct a dispatch_t from a dispatch_cfg_t.
   10  **/
   11 
   12 #define DISPATCH_PRIVATE
   13 #include "orconfig.h"
   14 
   15 #include "lib/dispatch/dispatch.h"
   16 #include "lib/dispatch/dispatch_st.h"
   17 #include "lib/dispatch/dispatch_cfg.h"
   18 #include "lib/dispatch/dispatch_cfg_st.h"
   19 
   20 #include "lib/cc/ctassert.h"
   21 #include "lib/intmath/cmp.h"
   22 #include "lib/malloc/malloc.h"
   23 #include "lib/log/util_bug.h"
   24 
   25 #include <string.h>
   26 
   27 /** Given a smartlist full of (possibly NULL) pointers to uint16_t values,
   28  * return the largest value, or dflt if the list is empty. */
   29 static int
   30 max_in_sl(const smartlist_t *sl, int dflt)
   31 {
   32   uint16_t *maxptr = NULL;
   33   SMARTLIST_FOREACH_BEGIN(sl, uint16_t *, u) {
   34     if (!maxptr)
   35       maxptr = u;
   36     else if (*u > *maxptr)
   37       maxptr = u;
   38   } SMARTLIST_FOREACH_END(u);
   39 
   40   return maxptr ? *maxptr : dflt;
   41 }
   42 
   43 /* The above function is only safe to call if we are sure that channel_id_t
   44  * and msg_type_id_t are really uint16_t.  They should be so defined in
   45  * msgtypes.h, but let's be extra cautious.
   46  */
   47 CTASSERT(sizeof(uint16_t) == sizeof(msg_type_id_t));
   48 CTASSERT(sizeof(uint16_t) == sizeof(channel_id_t));
   49 
   50 /** Helper: Format an unformattable message auxiliary data item: just return a
   51 * copy of the string <>. */
   52 static char *
   53 type_fmt_nop(msg_aux_data_t arg)
   54 {
   55   (void)arg;
   56   return tor_strdup("<>");
   57 }
   58 
   59 /** Helper: Free an unfreeable message auxiliary data item: do nothing. */
   60 static void
   61 type_free_nop(msg_aux_data_t arg)
   62 {
   63   (void)arg;
   64 }
   65 
   66 /** Type functions to use when no type functions are provided. */
   67 static dispatch_typefns_t nop_typefns = {
   68   .free_fn = type_free_nop,
   69   .fmt_fn = type_fmt_nop
   70 };
   71 
   72 /**
   73  * Alert function to use when none is configured: do nothing.
   74  **/
   75 static void
   76 alert_fn_nop(dispatch_t *d, channel_id_t ch, void *arg)
   77 {
   78   (void)d;
   79   (void)ch;
   80   (void)arg;
   81 }
   82 
   83 /**
   84  * Given a list of recvfn_t, create and return a new dtbl_entry_t mapping
   85  * to each of those functions.
   86  **/
   87 static dtbl_entry_t *
   88 dtbl_entry_from_lst(smartlist_t *receivers)
   89 {
   90   if (!receivers)
   91     return NULL;
   92 
   93   size_t n_recv = smartlist_len(receivers);
   94   dtbl_entry_t *ent;
   95   ent = tor_malloc_zero(offsetof(dtbl_entry_t, rcv) +
   96                         sizeof(dispatch_rcv_t) * n_recv);
   97 
   98   ent->n_fns = n_recv;
   99 
  100   SMARTLIST_FOREACH_BEGIN(receivers, const dispatch_rcv_t *, rcv) {
  101     memcpy(&ent->rcv[rcv_sl_idx], rcv, sizeof(*rcv));
  102     if (rcv->enabled) {
  103       ++ent->n_enabled;
  104     }
  105   } SMARTLIST_FOREACH_END(rcv);
  106 
  107   return ent;
  108 }
  109 
  110 /** Create and return a new dispatcher from a given dispatch_cfg_t. */
  111 dispatch_t *
  112 dispatch_new(const dispatch_cfg_t *cfg)
  113 {
  114   dispatch_t *d = tor_malloc_zero(sizeof(dispatch_t));
  115 
  116   /* Any message that has a type or a receiver counts towards our messages */
  117   const size_t n_msgs = MAX(smartlist_len(cfg->type_by_msg),
  118                             smartlist_len(cfg->recv_by_msg)) + 1;
  119 
  120   /* Any channel that any message has counts towards the number of channels. */
  121   const size_t n_chans = (size_t) MAX(1, max_in_sl(cfg->chan_by_msg,0)) + 1;
  122 
  123   /* Any type that a message has, or that has functions, counts towards
  124    * the number of types. */
  125   const size_t n_types = (size_t) MAX(max_in_sl(cfg->type_by_msg,0),
  126                                       smartlist_len(cfg->fns_by_type)) + 1;
  127 
  128   d->n_msgs = n_msgs;
  129   d->n_queues = n_chans;
  130   d->n_types = n_types;
  131 
  132   /* Initialize the array of type-functions. */
  133   d->typefns = tor_calloc(n_types, sizeof(dispatch_typefns_t));
  134   for (size_t i = 0; i < n_types; ++i) {
  135     /* Default to no-op for everything... */
  136     memcpy(&d->typefns[i], &nop_typefns, sizeof(dispatch_typefns_t));
  137   }
  138   SMARTLIST_FOREACH_BEGIN(cfg->fns_by_type, dispatch_typefns_t *, fns) {
  139     /* Set the functions if they are provided. */
  140     if (fns) {
  141       if (fns->free_fn)
  142         d->typefns[fns_sl_idx].free_fn = fns->free_fn;
  143       if (fns->fmt_fn)
  144         d->typefns[fns_sl_idx].fmt_fn = fns->fmt_fn;
  145     }
  146   } SMARTLIST_FOREACH_END(fns);
  147 
  148   /* Initialize the message queues: one for each channel. */
  149   d->queues = tor_calloc(d->n_queues, sizeof(dqueue_t));
  150   for (size_t i = 0; i < d->n_queues; ++i) {
  151     TOR_SIMPLEQ_INIT(&d->queues[i].queue);
  152     d->queues[i].alert_fn = alert_fn_nop;
  153   }
  154 
  155   /* Build the dispatch tables mapping message IDs to receivers. */
  156   d->table = tor_calloc(d->n_msgs, sizeof(dtbl_entry_t *));
  157   SMARTLIST_FOREACH_BEGIN(cfg->recv_by_msg, smartlist_t *, rcv) {
  158     d->table[rcv_sl_idx] = dtbl_entry_from_lst(rcv);
  159   } SMARTLIST_FOREACH_END(rcv);
  160 
  161   /* Fill in the empty entries in the dispatch tables:
  162    * types and channels for each message. */
  163   SMARTLIST_FOREACH_BEGIN(cfg->type_by_msg, msg_type_id_t *, type) {
  164     if (d->table[type_sl_idx])
  165       d->table[type_sl_idx]->type = *type;
  166   } SMARTLIST_FOREACH_END(type);
  167 
  168   SMARTLIST_FOREACH_BEGIN(cfg->chan_by_msg, channel_id_t *, chan) {
  169     if (d->table[chan_sl_idx])
  170       d->table[chan_sl_idx]->channel = *chan;
  171   } SMARTLIST_FOREACH_END(chan);
  172 
  173   return d;
  174 }