dispatch_cfg.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. /** DOCDOC */
  35. #define ID_TO_VOID(id) ((void*)(uintptr_t)(id))
  36. /**
  37. * Associate a message with a datatype. Return 0 on success, -1 if a
  38. * different type was previously associated with the message ID.
  39. **/
  40. int
  41. dcfg_msg_set_type(dispatch_cfg_t *cfg, message_id_t msg,
  42. msg_type_id_t type)
  43. {
  44. smartlist_grow(cfg->type_by_msg, msg+1);
  45. void *oldval = smartlist_get(cfg->type_by_msg, msg);
  46. if (oldval != NULL && oldval != ID_TO_VOID(type)) {
  47. return -1;
  48. }
  49. smartlist_set(cfg->type_by_msg, msg, ID_TO_VOID(type));
  50. return 0;
  51. }
  52. /**
  53. * Associate a message with a channel. Return 0 on success, -1 if a
  54. * different channel was previously associated with the message ID.
  55. **/
  56. int
  57. dcfg_msg_set_chan(dispatch_cfg_t *cfg, message_id_t msg,
  58. channel_id_t chan)
  59. {
  60. smartlist_grow(cfg->chan_by_msg, msg+1);
  61. void *oldval = smartlist_get(cfg->chan_by_msg, msg);
  62. if (oldval != NULL && oldval != ID_TO_VOID(chan)) {
  63. return -1;
  64. }
  65. smartlist_set(cfg->chan_by_msg, msg, ID_TO_VOID(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. smartlist_set(cfg->fns_by_type, type, (dispatch_typefns_t *) fns);
  82. return 0;
  83. }
  84. /**
  85. * Associate a receiver with a message ID. Multiple receivers may be
  86. * associated with a single messasge ID.
  87. *
  88. * Return 0 on success, on failure.
  89. **/
  90. int
  91. dcfg_add_recv(dispatch_cfg_t *cfg, message_id_t msg,
  92. subsys_id_t sys, recv_fn_t fn)
  93. {
  94. smartlist_grow(cfg->recv_by_msg, msg+1);
  95. smartlist_t *receivers = smartlist_get(cfg->recv_by_msg, msg);
  96. if (!receivers) {
  97. receivers = smartlist_new();
  98. smartlist_set(cfg->recv_by_msg, msg, receivers);
  99. }
  100. dispatch_rcv_t *rcv = tor_malloc(sizeof(dispatch_rcv_t));
  101. rcv->sys = sys;
  102. rcv->enabled = true;
  103. rcv->fn = fn;
  104. smartlist_add(receivers, (void*)rcv);
  105. return 0;
  106. }
  107. /** Helper: release all storage held by <b>cfg</b>. */
  108. void
  109. dcfg_free_(dispatch_cfg_t *cfg)
  110. {
  111. if (!cfg)
  112. return;
  113. smartlist_free(cfg->type_by_msg);
  114. smartlist_free(cfg->chan_by_msg);
  115. smartlist_free(cfg->fns_by_type);
  116. SMARTLIST_FOREACH_BEGIN(cfg->recv_by_msg, smartlist_t *, receivers) {
  117. if (!receivers)
  118. continue;
  119. SMARTLIST_FOREACH(receivers, dispatch_rcv_t *, rcv, tor_free(rcv));
  120. smartlist_free(receivers);
  121. } SMARTLIST_FOREACH_END(receivers);
  122. smartlist_free(cfg->recv_by_msg);
  123. tor_free(cfg);
  124. }