Line data Source code
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_cfg.c
9 : * \brief Create and configure a dispatch_cfg_t.
10 : *
11 : * A dispatch_cfg_t object is used to configure a set of messages and
12 : * associated information before creating a dispatch_t.
13 : */
14 :
15 : #define DISPATCH_PRIVATE
16 :
17 : #include "orconfig.h"
18 : #include "lib/dispatch/dispatch_cfg.h"
19 : #include "lib/dispatch/dispatch_cfg_st.h"
20 : #include "lib/dispatch/dispatch.h"
21 : #include "lib/dispatch/dispatch_st.h"
22 :
23 : #include "lib/container/smartlist.h"
24 : #include "lib/malloc/malloc.h"
25 :
26 : /**
27 : * Create and return a new dispatch_cfg_t.
28 : **/
29 : dispatch_cfg_t *
30 267 : dcfg_new(void)
31 : {
32 267 : dispatch_cfg_t *cfg = tor_malloc(sizeof(dispatch_cfg_t));
33 267 : cfg->type_by_msg = smartlist_new();
34 267 : cfg->chan_by_msg = smartlist_new();
35 267 : cfg->fns_by_type = smartlist_new();
36 267 : cfg->recv_by_msg = smartlist_new();
37 267 : return cfg;
38 : }
39 :
40 : /**
41 : * Associate a message with a datatype. Return 0 on success, -1 if a
42 : * different type was previously associated with the message ID.
43 : **/
44 : int
45 7911 : dcfg_msg_set_type(dispatch_cfg_t *cfg, message_id_t msg,
46 : msg_type_id_t type)
47 : {
48 7911 : smartlist_grow(cfg->type_by_msg, msg+1);
49 7911 : msg_type_id_t *oldval = smartlist_get(cfg->type_by_msg, msg);
50 7911 : if (oldval != NULL && *oldval != type) {
51 : return -1;
52 : }
53 7910 : if (!oldval)
54 1278 : smartlist_set(cfg->type_by_msg, msg, tor_memdup(&type, sizeof(type)));
55 : return 0;
56 : }
57 :
58 : /**
59 : * Associate a message with a channel. Return 0 on success, -1 if a
60 : * different channel was previously associated with the message ID.
61 : **/
62 : int
63 7910 : dcfg_msg_set_chan(dispatch_cfg_t *cfg, message_id_t msg,
64 : channel_id_t chan)
65 : {
66 7910 : smartlist_grow(cfg->chan_by_msg, msg+1);
67 7910 : channel_id_t *oldval = smartlist_get(cfg->chan_by_msg, msg);
68 7910 : if (oldval != NULL && *oldval != chan) {
69 : return -1;
70 : }
71 7909 : if (!oldval)
72 1278 : smartlist_set(cfg->chan_by_msg, msg, tor_memdup(&chan, sizeof(chan)));
73 : return 0;
74 : }
75 :
76 : /**
77 : * Associate a set of functions with a datatype. Return 0 on success, -1 if
78 : * different functions were previously associated with the type.
79 : **/
80 : int
81 1260 : dcfg_type_set_fns(dispatch_cfg_t *cfg, msg_type_id_t type,
82 : const dispatch_typefns_t *fns)
83 : {
84 1260 : smartlist_grow(cfg->fns_by_type, type+1);
85 1260 : dispatch_typefns_t *oldfns = smartlist_get(cfg->fns_by_type, type);
86 1260 : if (oldfns && (oldfns->free_fn != fns->free_fn ||
87 2 : oldfns->fmt_fn != fns->fmt_fn))
88 : return -1;
89 1257 : if (!oldfns)
90 1256 : smartlist_set(cfg->fns_by_type, type, tor_memdup(fns, sizeof(*fns)));
91 : return 0;
92 : }
93 :
94 : /**
95 : * Associate a receiver with a message ID. Multiple receivers may be
96 : * associated with a single messasge ID.
97 : *
98 : * Return 0 on success, on failure.
99 : **/
100 : int
101 6628 : dcfg_add_recv(dispatch_cfg_t *cfg, message_id_t msg,
102 : subsys_id_t sys, recv_fn_t fn)
103 : {
104 6628 : smartlist_grow(cfg->recv_by_msg, msg+1);
105 6628 : smartlist_t *receivers = smartlist_get(cfg->recv_by_msg, msg);
106 6628 : if (!receivers) {
107 1270 : receivers = smartlist_new();
108 1270 : smartlist_set(cfg->recv_by_msg, msg, receivers);
109 : }
110 :
111 6628 : dispatch_rcv_t *rcv = tor_malloc(sizeof(dispatch_rcv_t));
112 6628 : rcv->sys = sys;
113 6628 : rcv->enabled = true;
114 6628 : rcv->fn = fn;
115 6628 : smartlist_add(receivers, (void*)rcv);
116 6628 : return 0;
117 : }
118 :
119 : /** Helper: release all storage held by <b>cfg</b>. */
120 : void
121 267 : dcfg_free_(dispatch_cfg_t *cfg)
122 : {
123 267 : if (!cfg)
124 : return;
125 :
126 1550 : SMARTLIST_FOREACH(cfg->type_by_msg, msg_type_id_t *, id, tor_free(id));
127 1550 : SMARTLIST_FOREACH(cfg->chan_by_msg, channel_id_t *, id, tor_free(id));
128 1533 : SMARTLIST_FOREACH(cfg->fns_by_type, dispatch_typefns_t *, f, tor_free(f));
129 267 : smartlist_free(cfg->type_by_msg);
130 267 : smartlist_free(cfg->chan_by_msg);
131 267 : smartlist_free(cfg->fns_by_type);
132 1549 : SMARTLIST_FOREACH_BEGIN(cfg->recv_by_msg, smartlist_t *, receivers) {
133 1282 : if (!receivers)
134 12 : continue;
135 7898 : SMARTLIST_FOREACH(receivers, dispatch_rcv_t *, rcv, tor_free(rcv));
136 1270 : smartlist_free(receivers);
137 1282 : } SMARTLIST_FOREACH_END(receivers);
138 267 : smartlist_free(cfg->recv_by_msg);
139 :
140 267 : tor_free(cfg);
141 : }
|