dispatch_cfg.c 4.0 KB

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