dispatch_cfg.c (4087B)
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 dcfg_new(void) 31 { 32 dispatch_cfg_t *cfg = tor_malloc(sizeof(dispatch_cfg_t)); 33 cfg->type_by_msg = smartlist_new(); 34 cfg->chan_by_msg = smartlist_new(); 35 cfg->fns_by_type = smartlist_new(); 36 cfg->recv_by_msg = smartlist_new(); 37 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 dcfg_msg_set_type(dispatch_cfg_t *cfg, message_id_t msg, 46 msg_type_id_t type) 47 { 48 smartlist_grow(cfg->type_by_msg, msg+1); 49 msg_type_id_t *oldval = smartlist_get(cfg->type_by_msg, msg); 50 if (oldval != NULL && *oldval != type) { 51 return -1; 52 } 53 if (!oldval) 54 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 dcfg_msg_set_chan(dispatch_cfg_t *cfg, message_id_t msg, 64 channel_id_t chan) 65 { 66 smartlist_grow(cfg->chan_by_msg, msg+1); 67 channel_id_t *oldval = smartlist_get(cfg->chan_by_msg, msg); 68 if (oldval != NULL && *oldval != chan) { 69 return -1; 70 } 71 if (!oldval) 72 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 dcfg_type_set_fns(dispatch_cfg_t *cfg, msg_type_id_t type, 82 const dispatch_typefns_t *fns) 83 { 84 smartlist_grow(cfg->fns_by_type, type+1); 85 dispatch_typefns_t *oldfns = smartlist_get(cfg->fns_by_type, type); 86 if (oldfns && (oldfns->free_fn != fns->free_fn || 87 oldfns->fmt_fn != fns->fmt_fn)) 88 return -1; 89 if (!oldfns) 90 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 message ID. 97 * 98 * Return 0 on success, on failure. 99 **/ 100 int 101 dcfg_add_recv(dispatch_cfg_t *cfg, message_id_t msg, 102 subsys_id_t sys, recv_fn_t fn) 103 { 104 smartlist_grow(cfg->recv_by_msg, msg+1); 105 smartlist_t *receivers = smartlist_get(cfg->recv_by_msg, msg); 106 if (!receivers) { 107 receivers = smartlist_new(); 108 smartlist_set(cfg->recv_by_msg, msg, receivers); 109 } 110 111 dispatch_rcv_t *rcv = tor_malloc(sizeof(dispatch_rcv_t)); 112 rcv->sys = sys; 113 rcv->enabled = true; 114 rcv->fn = fn; 115 smartlist_add(receivers, (void*)rcv); 116 return 0; 117 } 118 119 /** Helper: release all storage held by <b>cfg</b>. */ 120 void 121 dcfg_free_(dispatch_cfg_t *cfg) 122 { 123 if (!cfg) 124 return; 125 126 SMARTLIST_FOREACH(cfg->type_by_msg, msg_type_id_t *, id, tor_free(id)); 127 SMARTLIST_FOREACH(cfg->chan_by_msg, channel_id_t *, id, tor_free(id)); 128 SMARTLIST_FOREACH(cfg->fns_by_type, dispatch_typefns_t *, f, tor_free(f)); 129 smartlist_free(cfg->type_by_msg); 130 smartlist_free(cfg->chan_by_msg); 131 smartlist_free(cfg->fns_by_type); 132 SMARTLIST_FOREACH_BEGIN(cfg->recv_by_msg, smartlist_t *, receivers) { 133 if (!receivers) 134 continue; 135 SMARTLIST_FOREACH(receivers, dispatch_rcv_t *, rcv, tor_free(rcv)); 136 smartlist_free(receivers); 137 } SMARTLIST_FOREACH_END(receivers); 138 smartlist_free(cfg->recv_by_msg); 139 140 tor_free(cfg); 141 }