LCOV - code coverage report
Current view: top level - lib/dispatch - dispatch_cfg.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 54 54 100.0 %
Date: 2021-11-24 03:28:48 Functions: 6 6 100.0 %

          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             : }

Generated by: LCOV version 1.14