orconn_event.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /* Copyright (c) 2007-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file orconn_event.c
  5. * \brief Publish state change messages for OR connections
  6. *
  7. * Implements a basic publish-subscribe framework for messages about
  8. * the state of OR connections. The publisher calls the subscriber
  9. * callback functions synchronously.
  10. *
  11. * Although the synchronous calls might not simplify the call graph,
  12. * this approach improves data isolation because the publisher doesn't
  13. * need knowledge about the internals of subscribing subsystems. It
  14. * also avoids race conditions that might occur in asynchronous
  15. * frameworks.
  16. **/
  17. #include "core/or/or.h"
  18. #include "lib/subsys/subsys.h"
  19. #define ORCONN_EVENT_PRIVATE
  20. #include "core/or/orconn_event.h"
  21. #include "core/or/orconn_event_sys.h"
  22. /** List of subscribers */
  23. static smartlist_t *orconn_event_rcvrs;
  24. /** Initialize subscriber list */
  25. static int
  26. orconn_event_init(void)
  27. {
  28. orconn_event_rcvrs = smartlist_new();
  29. return 0;
  30. }
  31. /** Free subscriber list */
  32. static void
  33. orconn_event_fini(void)
  34. {
  35. smartlist_free(orconn_event_rcvrs);
  36. }
  37. /**
  38. * Subscribe to messages about OR connection events
  39. *
  40. * Register a callback function to receive messages about ORCONNs.
  41. * The publisher calls this function synchronously.
  42. **/
  43. void
  44. orconn_event_subscribe(orconn_event_rcvr_t fn)
  45. {
  46. tor_assert(fn);
  47. /* Don't duplicate subscriptions. */
  48. if (smartlist_contains(orconn_event_rcvrs, fn))
  49. return;
  50. smartlist_add(orconn_event_rcvrs, fn);
  51. }
  52. /**
  53. * Publish a message about OR connection events
  54. *
  55. * This calls the subscriber receiver function synchronously.
  56. **/
  57. void
  58. orconn_event_publish(const orconn_event_msg_t *msg)
  59. {
  60. SMARTLIST_FOREACH_BEGIN(orconn_event_rcvrs, orconn_event_rcvr_t, fn) {
  61. tor_assert(fn);
  62. (*fn)(msg);
  63. } SMARTLIST_FOREACH_END(fn);
  64. }
  65. const subsys_fns_t sys_orconn_event = {
  66. .name = "orconn_event",
  67. .supported = true,
  68. .level = -33,
  69. .initialize = orconn_event_init,
  70. .shutdown = orconn_event_fini,
  71. };