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