tor  0.4.2.1-alpha-dev
dispatch_new.c
Go to the documentation of this file.
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 
12 #define DISPATCH_PRIVATE
13 #include "orconfig.h"
14 
15 #include "lib/dispatch/dispatch.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 
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 
52 static char *
54 {
55  (void)arg;
56  return tor_strdup("<>");
57 }
58 
60 static void
62 {
63  (void)arg;
64 }
65 
69  .fmt_fn = type_fmt_nop
70 };
71 
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 
87 static dtbl_entry_t *
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 
111 dispatch_t *
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  }
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 *));
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. */
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 }
struct smartlist_t * chan_by_msg
static void type_free_nop(msg_aux_data_t arg)
Definition: dispatch_new.c:61
static void alert_fn_nop(dispatch_t *d, channel_id_t ch, void *arg)
Definition: dispatch_new.c:76
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define CTASSERT(x)
Definition: ctassert.h:44
Macro definitions for MIN, MAX, and CLAMP.
Headers for util_malloc.c.
struct dispatch_t dispatch_t
Definition: dispatch.h:53
struct smartlist_t * recv_by_msg
void(* free_fn)(msg_aux_data_t)
Definition: msgtypes.h:74
Low-level APIs for message-passing system.
dispatch_t * dispatch_new(const dispatch_cfg_t *cfg)
Definition: dispatch_new.c:112
static dispatch_typefns_t nop_typefns
Definition: dispatch_new.c:67
static dtbl_entry_t * dtbl_entry_from_lst(smartlist_t *receivers)
Definition: dispatch_new.c:88
uint16_t msg_type_id_t
Definition: msgtypes.h:29
Compile-time assertions: CTASSERT(expression).
struct smartlist_t * type_by_msg
private structures used for the dispatcher module
static char * type_fmt_nop(msg_aux_data_t arg)
Definition: dispatch_new.c:53
#define MAX(a, b)
Definition: cmp.h:22
static int max_in_sl(const smartlist_t *sl, int dflt)
Definition: dispatch_new.c:30
struct smartlist_t * fns_by_type
Macros to manage assertions, fatal and non-fatal.