mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
e4d3098d4d
This module implements a way to send messages from one module to another, with associated data types. It does not yet do anything to ensure that messages are correct, that types match, or that other forms of consistency are preserved.
139 lines
3.8 KiB
C
139 lines
3.8 KiB
C
/* 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;
|
|
}
|
|
|
|
/** DOCDOC */
|
|
#define ID_TO_VOID(id) ((void*)(uintptr_t)(id))
|
|
|
|
/**
|
|
* 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);
|
|
void *oldval = smartlist_get(cfg->type_by_msg, msg);
|
|
if (oldval != NULL && oldval != ID_TO_VOID(type)) {
|
|
return -1;
|
|
}
|
|
smartlist_set(cfg->type_by_msg, msg, ID_TO_VOID(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);
|
|
void *oldval = smartlist_get(cfg->chan_by_msg, msg);
|
|
if (oldval != NULL && oldval != ID_TO_VOID(chan)) {
|
|
return -1;
|
|
}
|
|
smartlist_set(cfg->chan_by_msg, msg, ID_TO_VOID(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;
|
|
smartlist_set(cfg->fns_by_type, type, (dispatch_typefns_t *) 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_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);
|
|
}
|