aboutsummaryrefslogtreecommitdiff
path: root/src/lib/subsys/subsys.h
blob: 62c0de026d62e8ab81f9ae873a0694afed2e80fa (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/* Copyright (c) 2003-2004, Roger Dingledine
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * @file subsys.h
 * @brief Types used to declare a subsystem.
 **/

#ifndef TOR_SUBSYS_T
#define TOR_SUBSYS_T

#include <stdbool.h>

struct pubsub_connector_t;
struct config_format_t;

/**
 * A subsystem is a part of Tor that is initialized, shut down, configured,
 * and connected to other parts of Tor.
 *
 * All callbacks are optional -- if a callback is set to NULL, the subsystem
 * manager will treat it as a no-op.
 *
 * You should use c99 named-field initializers with this structure, for
 * readability and safety. (There are a lot of functions here, all of them
 * optional, and many of them with similar signatures.)
 *
 * See @ref initialization for more information about initialization and
 * shutdown in Tor.
 *
 * To make a new subsystem, you declare a const instance of this type, and
 * include it on the list in subsystem_list.c.  The code that manages these
 * subsystems is in subsysmgr.c.
 **/
typedef struct subsys_fns_t {
  /**
   * The name of this subsystem.  It should be a programmer-readable
   * identifier.
   **/
  const char *name;

  /**
   * The file in which the subsystem object is declared. Used for debugging.
   **/
  const char *location;

  /**
   * Whether this subsystem is supported -- that is, whether it is compiled
   * into Tor.  For most subsystems, this should be true.
   **/
  bool supported;

  /**
   * The 'initialization level' for the subsystem.  It should run from -100
   * through +100.  The subsystems are initialized from lowest level to
   * highest, and shut down from highest level to lowest.
   **/
  int level;

  /**
   * Initialize any global components of this subsystem.
   *
   * This function MAY rely on any lower-level subsystem being initialized.
   *
   * This function MUST NOT rely on any runtime configuration information;
   * it is only for global state or pre-configuration state.
   *
   * (If you need to do any setup that depends on configuration, you'll need
   * to declare a configuration callback instead. (Not yet designed))
   *
   * This function MUST NOT have any parts that can fail.
   **/
  int (*initialize)(void);

  /**
   * Connect a subsystem to the message dispatch system.
   *
   * This function should use the macros in @refdir{lib/pubsub} to register a
   * set of messages that this subsystem may publish, and may subscribe to.
   *
   * See pubsub_macros.h for more information, and for examples.
   **/
  int (*add_pubsub)(struct pubsub_connector_t *);

  /**
   * Perform any necessary pre-fork cleanup.  This function may not fail.
   *
   * On Windows (and any other platforms without fork()), this function will
   * never be invoked.  Otherwise it is used when we are about to start
   * running as a background daemon, or when we are about to run a unit test
   * in a subprocess.  Unlike the subsys_fns_t.postfork callback, it is run
   * from the parent process.
   *
   * Note that we do not invoke this function when the child process's only
   * purpose is to call exec() and run another program.
   */
  void (*prefork)(void);

  /**
   * Perform any necessary post-fork setup. This function may not fail.
   *
   * On Windows (and any other platforms without fork()), this function will
   * never be invoked.  Otherwise it is used when we are about to start
   * running as a background daemon, or when we are about to run a unit test
   * in a subprocess.  Unlike the subsys_fns_t.prefork callback, it is run
   * from the child process.
   *
   * Note that we do not invoke this function when the child process's only
   * purpose is to call exec() and run another program.
   */
  void (*postfork)(void);

  /**
   * Free any thread-local resources held by this subsystem. Called before
   * the thread exits.
   *
   * This function is not allowed to fail.
   *
   * \bug Note that this callback is currently buggy: See \ticket{32103}.
   */
  void (*thread_cleanup)(void);

  /**
   * Free all resources held by this subsystem.
   *
   * This function is not allowed to fail.
   *
   * Subsystems are shut down when Tor is about to exit or return control to
   * an embedding program. This callback must return the process to a state
   * such that subsys_fns_t.init will succeed if invoked again.
   **/
  void (*shutdown)(void);

  /**
   * A config_format_t describing all of the torrc fields owned by this
   * subsystem.
   *
   * This object, if present, is registered in a confmgr_t for Tor's options,
   * and used to parse option fields from the command line and torrc file.
   **/
  const struct config_format_t *options_format;

  /**
   * A config_format_t describing all of the DataDir/state fields owned by
   * this subsystem.
   *
   * This object, if present, is registered in a confmgr_t for Tor's state,
   * and used to parse state fields from the DataDir/state file.
   **/
  const struct config_format_t *state_format;

  /**
   * Receive an options object as defined by options_format. Return 0
   * on success, -1 on failure.
   *
   * It is safe to store the pointer to the object until set_options()
   * is called again.
   *
   * This function is only called after all the validation code defined
   * by subsys_fns_t.options_format has passed.
   **/
  int (*set_options)(void *);

  /* XXXX Add an implementation for options_act_reversible() later in this
   * branch. */

  /**
   * Receive a state object as defined by state_format. Return 0 on success,
   * -1 on failure.
   *
   * It is safe to store the pointer to the object; set_state() is only
   * called on startup.
   *
   * This function is only called after all the validation code defined
   * by subsys_fns_t.state_format has passed.
   *
   * This function will only be called once per invocation of Tor, since
   * Tor does not reload its state while it is running.
   **/
  int (*set_state)(void *);

  /**
   * Update any information that needs to be stored in the provided state
   * object (as defined by state_format).  Return 0 on success, -1 on failure.
   *
   * The object provided here will be the same one as provided earlier to
   * set_state().  This method is called when we are about to save the state
   * to disk.
   **/
  int (*flush_state)(void *);
} subsys_fns_t;

#ifndef COCCI
/**
 * Macro to declare a subsystem's location.
 **/
#define SUBSYS_DECLARE_LOCATION() \
  .location = __FILE__
#endif /* !defined(COCCI) */

/**
 * Lowest allowed subsystem level.
 **/
#define MIN_SUBSYS_LEVEL -100
/**
 * Highest allowed subsystem level.
 **/
#define MAX_SUBSYS_LEVEL 100

/**
 * All tor "libraries" (in src/libs) should have a subsystem level equal to or
 * less than this value.
 */
#define SUBSYS_LEVEL_LIBS -10

#endif /* !defined(TOR_SUBSYS_T) */