123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- /* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- /**
- * \file dispatch_cfg.c
- * \brief Create and configure a dispatch_cfg_t.
- *
- * A dispatch_cfg_t object is used to configure a set of messages and
- * associated information before creating a dispatch_t.
- */
- #define DISPATCH_PRIVATE
- #include "orconfig.h"
- #include "lib/dispatch/dispatch_cfg.h"
- #include "lib/dispatch/dispatch_cfg_st.h"
- #include "lib/dispatch/dispatch.h"
- #include "lib/dispatch/dispatch_st.h"
- #include "lib/container/smartlist.h"
- #include "lib/malloc/malloc.h"
- /**
- * Create and return a new dispatch_cfg_t.
- **/
- dispatch_cfg_t *
- dcfg_new(void)
- {
- dispatch_cfg_t *cfg = tor_malloc(sizeof(dispatch_cfg_t));
- cfg->type_by_msg = smartlist_new();
- cfg->chan_by_msg = smartlist_new();
- cfg->fns_by_type = smartlist_new();
- cfg->recv_by_msg = smartlist_new();
- return cfg;
- }
- /**
- * Associate a message with a datatype. Return 0 on success, -1 if a
- * different type was previously associated with the message ID.
- **/
- int
- dcfg_msg_set_type(dispatch_cfg_t *cfg, message_id_t msg,
- msg_type_id_t type)
- {
- smartlist_grow(cfg->type_by_msg, msg+1);
- msg_type_id_t *oldval = smartlist_get(cfg->type_by_msg, msg);
- if (oldval != NULL && *oldval != type) {
- return -1;
- }
- if (!oldval)
- smartlist_set(cfg->type_by_msg, msg, tor_memdup(&type, sizeof(type)));
- return 0;
- }
- /**
- * Associate a message with a channel. Return 0 on success, -1 if a
- * different channel was previously associated with the message ID.
- **/
- int
- dcfg_msg_set_chan(dispatch_cfg_t *cfg, message_id_t msg,
- channel_id_t chan)
- {
- smartlist_grow(cfg->chan_by_msg, msg+1);
- channel_id_t *oldval = smartlist_get(cfg->chan_by_msg, msg);
- if (oldval != NULL && *oldval != chan) {
- return -1;
- }
- if (!oldval)
- smartlist_set(cfg->chan_by_msg, msg, tor_memdup(&chan, sizeof(chan)));
- return 0;
- }
- /**
- * Associate a set of functions with a datatype. Return 0 on success, -1 if
- * different functions were previously associated with the type.
- **/
- int
- dcfg_type_set_fns(dispatch_cfg_t *cfg, msg_type_id_t type,
- const dispatch_typefns_t *fns)
- {
- smartlist_grow(cfg->fns_by_type, type+1);
- dispatch_typefns_t *oldfns = smartlist_get(cfg->fns_by_type, type);
- if (oldfns && (oldfns->free_fn != fns->free_fn ||
- oldfns->fmt_fn != fns->fmt_fn))
- return -1;
- if (!oldfns)
- smartlist_set(cfg->fns_by_type, type, tor_memdup(fns, sizeof(*fns)));
- return 0;
- }
- /**
- * Associate a receiver with a message ID. Multiple receivers may be
- * associated with a single messasge ID.
- *
- * Return 0 on success, on failure.
- **/
- int
- dcfg_add_recv(dispatch_cfg_t *cfg, message_id_t msg,
- subsys_id_t sys, recv_fn_t fn)
- {
- smartlist_grow(cfg->recv_by_msg, msg+1);
- smartlist_t *receivers = smartlist_get(cfg->recv_by_msg, msg);
- if (!receivers) {
- receivers = smartlist_new();
- smartlist_set(cfg->recv_by_msg, msg, receivers);
- }
- dispatch_rcv_t *rcv = tor_malloc(sizeof(dispatch_rcv_t));
- rcv->sys = sys;
- rcv->enabled = true;
- rcv->fn = fn;
- smartlist_add(receivers, (void*)rcv);
- return 0;
- }
- /** Helper: release all storage held by <b>cfg</b>. */
- void
- dcfg_free_(dispatch_cfg_t *cfg)
- {
- if (!cfg)
- return;
- SMARTLIST_FOREACH(cfg->type_by_msg, msg_type_id_t *, id, tor_free(id));
- SMARTLIST_FOREACH(cfg->chan_by_msg, channel_id_t *, id, tor_free(id));
- SMARTLIST_FOREACH(cfg->fns_by_type, dispatch_typefns_t *, f, tor_free(f));
- smartlist_free(cfg->type_by_msg);
- smartlist_free(cfg->chan_by_msg);
- smartlist_free(cfg->fns_by_type);
- SMARTLIST_FOREACH_BEGIN(cfg->recv_by_msg, smartlist_t *, receivers) {
- if (!receivers)
- continue;
- SMARTLIST_FOREACH(receivers, dispatch_rcv_t *, rcv, tor_free(rcv));
- smartlist_free(receivers);
- } SMARTLIST_FOREACH_END(receivers);
- smartlist_free(cfg->recv_by_msg);
- tor_free(cfg);
- }
|