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