pubsub_macros.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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 pubsub_macros.h
  8. * \brief Macros to help with the publish/subscribe dispatch API.
  9. *
  10. * The dispatch API allows different subsystems of Tor to communicate with
  11. * another asynchronously via a shared "message" system. Some subsystems
  12. * declare that they publish a given message, and others declare that they
  13. * subscribe to it. Both subsystems depend on the message, but not upon one
  14. * another.
  15. *
  16. * To declare a message, use DECLARE_MESSAGE() (for messages that take their
  17. * data as a pointer) or DECLARE_MESSAGE_INT() (for messages that take their
  18. * data as an integer. For example, you might say
  19. *
  20. * DECLARE_MESSAGE(new_circuit, circ, circuit_handle_t *);
  21. * or
  22. * DECLARE_MESSAGE_INT(shutdown_requested, boolean, bool);
  23. *
  24. * Every message has a unique name, a "type name" that the dispatch system
  25. * uses to manage associated data, and a C type name. You'll want to put
  26. * these declarations in a header, to be included by all publishers and all
  27. * subscribers.
  28. *
  29. * When a subsystem wants to publish a message, it uses DECLARE_PUBLISH() at
  30. * file scope to create necessary static functions. Then, in its subsystem
  31. * initialization (in the "bind to dispatcher" callback) (TODO: name this
  32. * properly!), it calls DISPATCH_ADD_PUB() to tell the dispatcher about its
  33. * intent to publish. When it actually wants to publish, it uses the
  34. * PUBLISH() macro. For example:
  35. *
  36. * // At file scope
  37. * DECLARE_PUBLISH(shutdown_requested);
  38. *
  39. * static void bind_to_dispatcher(pubsub_connector_t *con)
  40. * {
  41. * DISPATCH_ADD_PUB(con, mainchannel, shutdown_requested);
  42. * }
  43. *
  44. * // somewhere in a function
  45. * {
  46. * PUBLISH(shutdown_requested, true);
  47. * }
  48. *
  49. * When a subsystem wants to subscribe to a message, it uses
  50. * DECLARE_SUBSCRIBE() at file scope to declare static functions. It must
  51. * declare a hook function that receives the message type. Then, in its "bind
  52. * to dispatcher" function, it calls DISPATCHER_ADD_SUB() to tell the
  53. * dispatcher about its intent to subscribe. When another module publishes
  54. * the message, the dispatcher will call the provided hook function.
  55. *
  56. * // At file scope. The first argument is the message that you're
  57. * // subscribing to; the second argument is the hook function to declare.
  58. * DECLARE_SUBSCRIBE(shutdown_requested, on_shutdown_req_cb);
  59. *
  60. * // You need to declare this function.
  61. * static void on_shutdown_req_cb(const msg_t *msg,
  62. * bool value)
  63. * {
  64. * // (do something here.)
  65. * }
  66. *
  67. * static void bind_to_dispatcher(pubsub_connector_t *con)
  68. * {
  69. * DISPATCH_ADD_SUB(con, mainchannel, shutdown_requested);
  70. * }
  71. *
  72. * Where did these types come from? Somewhere in the code, you need to call
  73. * DISPATCH_REGISTER_TYPE() to make sure that the dispatcher can manage the
  74. * message auxiliary data. It associates a vtbl-like structure with the
  75. * type name, so that the dispatcher knows how to manipulate the type you're
  76. * giving it.
  77. *
  78. * For example, the "boolean" type we're using above could be defined as:
  79. *
  80. * static char *boolean_fmt(msg_aux_data_t d)
  81. * {
  82. * // This is used for debugging and dumping messages.
  83. * if (d.u64)
  84. * return tor_strdup("true");
  85. * else
  86. * return tor_strdup("false");
  87. * }
  88. *
  89. * static void boolean_free(msg_aux_data_t d)
  90. * {
  91. * // We don't actually need to do anything to free a boolean.
  92. * // We could use "NULL" instead of this function, but I'm including
  93. * // it as an example.
  94. * }
  95. *
  96. * static void bind_to_dispatcher(pubsub_connector_t *con)
  97. * {
  98. * dispatch_typefns_t boolean_fns = {
  99. * .fmt_fn = boolean_fmt,
  100. * .free_fn = boolean_free,
  101. * };
  102. * DISPATCH_REGISTER_TYPE(con, boolean, &boolean_fns);
  103. * }
  104. *
  105. *
  106. *
  107. * So, how does this all work? (You can stop reading here, unless you're
  108. * debugging something.)
  109. *
  110. * When you declare a message in a header with DECLARE_MESSAGE() or
  111. * DECLARE_MESSAGE_INT(), it creates five things:
  112. *
  113. * * two typedefs for the message argument (constant and non-constant
  114. * variants).
  115. * * a constant string to hold the declared message type name
  116. * * two inline functions, to coerce the message argument type to and from
  117. * a "msg_aux_data_t" union.
  118. *
  119. * All of these declarations have names based on the message name.
  120. *
  121. * Later, when you say DECLARE_PUBLISH() or DECLARE_SUBSCRIBE(), we use the
  122. * elements defined by DECLARE_MESSAGE() to make sure that the publish
  123. * function takes the correct argument type, and that the subscription hook is
  124. * declared with the right argument type.
  125. **/
  126. #ifndef TOR_DISPATCH_MSG_H
  127. #define TOR_DISPATCH_MSG_H
  128. #include "lib/cc/compat_compiler.h"
  129. #include "lib/dispatch/dispatch_naming.h"
  130. #include "lib/pubsub/pub_binding_st.h"
  131. #include "lib/pubsub/pubsub_connect.h"
  132. #include "lib/pubsub/pubsub_flags.h"
  133. #include "lib/pubsub/pubsub_publish.h"
  134. /* Implemenation notes:
  135. *
  136. * For a messagename "foo", the DECLARE_MESSAGE*() macros must declare:
  137. *
  138. * msg_arg_type__foo -- a typedef for the argument type of the foo message.
  139. * msg_arg_consttype__foo -- a typedef for the const argument type of the
  140. * foo message.
  141. * msg_arg_name__foo[] -- a static string constant holding the unique
  142. * identifier for the type of the foo message.
  143. * msg_arg_get__foo() -- an inline function taking a msg_aux_data_t and
  144. * returning the C data type.
  145. * msg_arg_set__foo() -- an inline function taking a msg_aux_data_t and
  146. * the C type, setting the msg_aux_data_t to hold the C type.
  147. *
  148. * For a messagename "foo", the DECLARE_PUBLISH() macro must declare:
  149. *
  150. * pub_binding__foo -- A static pub_binding_t object used to send messages
  151. * from this module.
  152. * publish_fn__foo -- A function taking an argument of the appropriate
  153. * C type, to be invoked by PUBLISH().
  154. *
  155. * For a messagename "foo", the DECLARE_SUBSCRIBE() macro must declare:
  156. *
  157. * hookfn -- A user-provided function name, with the correct signature.
  158. * recv_fn__foo -- A wrapper callback that takes a msg_t *, and calls
  159. * hookfn with the appropriate arguments.
  160. */
  161. /* Macro to declare common elements shared by DECLARE_MESSAGE and
  162. * DECLARE_MESSAGE_INT. Don't call this directly.
  163. *
  164. * Note that the "msg_arg_name" string constant is defined in each
  165. * translation unit. This might be undesirable; we can tweak it in the
  166. * future if need be.
  167. */
  168. #define DECLARE_MESSAGE_COMMON__(messagename, typename, c_type) \
  169. typedef c_type msg_arg_type__ ##messagename; \
  170. typedef const c_type msg_arg_consttype__ ##messagename; \
  171. ATTR_UNUSED static const char msg_arg_name__ ##messagename[] = # typename;
  172. /**
  173. * Use this macro in a header to declare the existence of a given message,
  174. * taking a pointer as auxiliary data.
  175. *
  176. * "messagename" is a unique identifier for the message; it must be a valid
  177. * C identifier.
  178. *
  179. * "typename" is a unique identifier for the type of the auxiliary data.
  180. * It needs to be defined somewhere in Tor, using
  181. * "DISPATCH_REGISTER_TYPE."
  182. *
  183. * "c_ptr_type" is a C pointer type (like "char *" or "struct foo *").
  184. * The "*" needs to be included.
  185. */
  186. #define DECLARE_MESSAGE(messagename, typename, c_ptr_type) \
  187. DECLARE_MESSAGE_COMMON__(messagename, typename, c_ptr_type) \
  188. ATTR_UNUSED static inline c_ptr_type \
  189. msg_arg_get__ ##messagename(msg_aux_data_t m) \
  190. { \
  191. return m.ptr; \
  192. } \
  193. ATTR_UNUSED static inline void \
  194. msg_arg_set__ ##messagename(msg_aux_data_t *m, c_ptr_type v) \
  195. { \
  196. m->ptr = v; \
  197. } \
  198. EAT_SEMICOLON
  199. /**
  200. * Use this macro in a header to declare the existence of a given message,
  201. * taking an integer as auxiliary data.
  202. *
  203. * "messagename" is a unique identifier for the message; it must be a valid
  204. * C identifier.
  205. *
  206. * "typename" is a unique identifier for the type of the auxiliary data. It
  207. * needs to be defined somewhere in Tor, using "DISPATCH_REGISTER_TYPE."
  208. *
  209. * "c_type" is a C integer type, like "int" or "bool". It needs to fit inside
  210. * a uint64_t.
  211. */
  212. #define DECLARE_MESSAGE_INT(messagename, typename, c_type) \
  213. DECLARE_MESSAGE_COMMON__(messagename, typename, c_type) \
  214. ATTR_UNUSED static inline c_type \
  215. msg_arg_get__ ##messagename(msg_aux_data_t m) \
  216. { \
  217. return (c_type)m.u64; \
  218. } \
  219. ATTR_UNUSED static inline void \
  220. msg_arg_set__ ##messagename(msg_aux_data_t *m, c_type v) \
  221. { \
  222. m->u64 = (uint64_t)v; \
  223. } \
  224. EAT_SEMICOLON
  225. /**
  226. * Use this macro inside a C module declare that we'll be publishing a given
  227. * message type from within this module.
  228. *
  229. * It creates necessary functions and wrappers to publish a message whose
  230. * unique identifier is "messagename".
  231. *
  232. * Before you use this, you need to include the header where DECLARE_MESSAGE*()
  233. * was used for this message.
  234. *
  235. * You can only use this once per message in each subsystem.
  236. */
  237. #define DECLARE_PUBLISH(messagename) \
  238. static pub_binding_t pub_binding__ ##messagename; \
  239. static void \
  240. publish_fn__ ##messagename(msg_arg_type__ ##messagename arg) \
  241. { \
  242. msg_aux_data_t data; \
  243. msg_arg_set__ ##messagename(&data, arg); \
  244. pubsub_pub_(&pub_binding__ ##messagename, data); \
  245. } \
  246. EAT_SEMICOLON
  247. /**
  248. * Use this macro inside a C file to declare that we're subscribing to a
  249. * given message and associating it with a given "hook function". It
  250. * declares the hook function static, and helps with strong typing.
  251. *
  252. * Before you use this, you need to include the header where
  253. * DECLARE_MESSAGE*() was used for the message whose unique identifier is
  254. * "messagename".
  255. *
  256. * You will need to define a function with the name that you provide for
  257. * "hookfn". The type of this function will be:
  258. * static void hookfn(const msg_t *, const c_type)
  259. * where c_type is the c type that you declared in the header.
  260. *
  261. * You can only use this once per message in each subsystem.
  262. */
  263. #define DECLARE_SUBSCRIBE(messagename, hookfn) \
  264. static void hookfn(const msg_t *, \
  265. const msg_arg_consttype__ ##messagename); \
  266. static void recv_fn__ ## messagename(const msg_t *m) \
  267. { \
  268. msg_arg_type__ ## messagename arg; \
  269. arg = msg_arg_get__ ##messagename(m->aux_data__); \
  270. hookfn(m, arg); \
  271. } \
  272. EAT_SEMICOLON
  273. /**
  274. * Add a fake use of the publish function for 'messagename', so that
  275. * the compiler does not call it unused.
  276. */
  277. #define DISPATCH__FAKE_USE_OF_PUBFN_(messagename) \
  278. ( 0 ? (publish_fn__ ##messagename((msg_arg_type__##messagename)0), 1) \
  279. : 1)
  280. /*
  281. * This macro is for internal use. It backs DISPATCH_ADD_PUB*()
  282. */
  283. #define DISPATCH_ADD_PUB_(connector, channel, messagename, flags) \
  284. ( \
  285. DISPATCH__FAKE_USE_OF_PUBFN_(messagename), \
  286. pubsub_add_pub_((connector), \
  287. &pub_binding__ ##messagename, \
  288. get_channel_id(# channel), \
  289. get_message_id(# messagename), \
  290. get_msg_type_id(msg_arg_name__ ## messagename), \
  291. (flags), \
  292. __FILE__, \
  293. __LINE__) \
  294. )
  295. /**
  296. * Use a given connector and channel name to declare that this subsystem will
  297. * publish a given message type.
  298. *
  299. * Call this macro from within the add_subscriptions() function of a module.
  300. */
  301. #define DISPATCH_ADD_PUB(connector, channel, messagename) \
  302. DISPATCH_ADD_PUB_(connector, channel, messagename, 0)
  303. /**
  304. * Use a given connector and channel name to declare that this subsystem will
  305. * publish a given message type, and that no other subsystem is allowed to.
  306. *
  307. * Call this macro from within the add_subscriptions() function of a module.
  308. */
  309. #define DISPATCH_ADD_PUB_EXCL(connector, channel, messagename) \
  310. DISPATCH_ADD_PUB_(connector, channel, messagename, DISP_FLAG_EXCL)
  311. /*
  312. * This macro is for internal use. It backs DISPATCH_ADD_SUB*()
  313. */
  314. #define DISPATCH_ADD_SUB_(connector, channel, messagename, flags) \
  315. pubsub_add_sub_((connector), \
  316. recv_fn__ ##messagename, \
  317. get_channel_id(#channel), \
  318. get_message_id(# messagename), \
  319. get_msg_type_id(msg_arg_name__ ##messagename), \
  320. (flags), \
  321. __FILE__, \
  322. __LINE__)
  323. /*
  324. * Use a given connector and channel name to declare that this subsystem will
  325. * receive a given message type.
  326. *
  327. * Call this macro from within the add_subscriptions() function of a module.
  328. */
  329. #define DISPATCH_ADD_SUB(connector, channel, messagename) \
  330. DISPATCH_ADD_SUB_(connector, channel, messagename, 0)
  331. /**
  332. * Use a given connector and channel name to declare that this subsystem will
  333. * receive a given message type, and that no other subsystem is allowed to do
  334. * so.
  335. *
  336. * Call this macro from within the add_subscriptions() function of a module.
  337. */
  338. #define DISPATCH_ADD_SUB_EXCL(connector, channel, messagename) \
  339. DISPATCH_ADD_SUB_(connector, channel, messagename, DISP_FLAG_EXCL)
  340. /**
  341. * Publish a given message with a given argument. (Takes ownership of the
  342. * argument if it is a pointer.)
  343. */
  344. #define PUBLISH(messagename, arg) \
  345. publish_fn__ ##messagename(arg)
  346. /**
  347. * Use a given connector to declare that the functions to be used to manipuate
  348. * a certain C type.
  349. **/
  350. #define DISPATCH_REGISTER_TYPE(con, type, fns) \
  351. pubsub_connector_register_type_((con), \
  352. get_msg_type_id(#type), \
  353. (fns), \
  354. __FILE__, \
  355. __LINE__)
  356. #endif