blob: 4a6fc748c909cb2eeb5594e5970a138fe00e06b7 (
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
82
83
84
|
/* Copyright (c) 2007-2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file ocirc_event.c
* \brief Publish state change messages for origin circuits
*
* Implements a basic publish-subscribe framework for messages about
* the state of origin circuits. 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"
#define OCIRC_EVENT_PRIVATE
#include "core/or/cpath_build_state_st.h"
#include "core/or/ocirc_event.h"
#include "core/or/ocirc_event_sys.h"
#include "core/or/origin_circuit_st.h"
#include "lib/subsys/subsys.h"
/** List of subscribers */
static smartlist_t *ocirc_event_rcvrs;
/** Initialize subscriber list */
static int
ocirc_event_init(void)
{
ocirc_event_rcvrs = smartlist_new();
return 0;
}
/** Free subscriber list */
static void
ocirc_event_fini(void)
{
smartlist_free(ocirc_event_rcvrs);
}
/**
* Subscribe to messages about origin circuit events
*
* Register a callback function to receive messages about origin
* circuits. The publisher calls this function synchronously.
**/
void
ocirc_event_subscribe(ocirc_event_rcvr_t fn)
{
tor_assert(fn);
/* Don't duplicate subscriptions. */
if (smartlist_contains(ocirc_event_rcvrs, fn))
return;
smartlist_add(ocirc_event_rcvrs, fn);
}
/**
* Publish a message about OR connection events
*
* This calls the subscriber receiver function synchronously.
**/
void
ocirc_event_publish(const ocirc_event_msg_t *msg)
{
SMARTLIST_FOREACH_BEGIN(ocirc_event_rcvrs, ocirc_event_rcvr_t, fn) {
tor_assert(fn);
(*fn)(msg);
} SMARTLIST_FOREACH_END(fn);
}
const subsys_fns_t sys_ocirc_event = {
.name = "ocirc_event",
.supported = true,
.level = -32,
.initialize = ocirc_event_init,
.shutdown = ocirc_event_fini,
};
|