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-2021, The Tor Project, Inc. */ 5 /* See LICENSE for licensing information */ 6 7 #ifndef TOR_DISPATCH_H 8 #define TOR_DISPATCH_H 9 10 #include "lib/dispatch/msgtypes.h" 11 12 /** 13 * \file dispatch.h 14 * \brief Low-level APIs for message-passing system. 15 * 16 * This module implements message dispatch based on a set of short integer 17 * identifiers. For a higher-level interface, see pubsub.h. 18 * 19 * Each message is represented as a generic msg_t object, and is discriminated 20 * by its message_id_t. Messages are delivered by a dispatch_t object, which 21 * delivers each message to its recipients by a configured "channel". 22 * 23 * A "channel" is a means of delivering messages. Every message_id_t must 24 * be associated with exactly one channel, identified by channel_id_t. 25 * When a channel receives messages, a callback is invoked to either process 26 * the messages immediately, or to cause them to be processed later. 27 * 28 * Every message_id_t has zero or more associated receiver functions set up in 29 * the dispatch_t object. Once the dispatch_t object is created, receivers 30 * can be enabled or disabled [TODO], but not added or removed. 31 * 32 * Every message_id_t has an associated datatype, identified by a 33 * msg_type_id_t. These datatypes can be associated with functions to 34 * (for example) free them, or format them for debugging. 35 * 36 * To setup a dispatch_t object, first create a dispatch_cfg_t object, and 37 * configure messages with their types, channels, and receivers. Then, use 38 * dispatch_new() with that dispatch_cfg_t to create the dispatch_t object. 39 * 40 * (We use a two-phase construction procedure here to enable better static 41 * reasoning about publish/subscribe relationships.) 42 * 43 * Once you have a dispatch_t, you can queue messages on it with 44 * dispatch_send*(), and cause those messages to be delivered with 45 * dispatch_flush(). 46 **/ 47 48 /** 49 * A "dispatcher" is the highest-level object; it handles making sure that 50 * messages are received and delivered properly. Only the mainloop 51 * should handle this type directly. 52 */ 53 typedef struct dispatch_t dispatch_t; 54 55 struct dispatch_cfg_t; 56 57 dispatch_t *dispatch_new(const struct dispatch_cfg_t *cfg); 58 59 /** 60 * Free a dispatcher. Tor does this at exit. 61 */ 62 #define dispatch_free(d) \ 63 FREE_AND_NULL(dispatch_t, dispatch_free_, (d)) 64 65 void dispatch_free_(dispatch_t *); 66 67 int dispatch_send(dispatch_t *d, 68 subsys_id_t sender, 69 channel_id_t channel, 70 message_id_t msg, 71 msg_type_id_t type, 72 msg_aux_data_t auxdata); 73 74 int dispatch_send_msg(dispatch_t *d, msg_t *m); 75 76 int dispatch_send_msg_unchecked(dispatch_t *d, msg_t *m); 77 78 /* Flush up to <b>max_msgs</b> currently pending messages from the 79 * dispatcher. Messages that are not pending when this function are 80 * called, are not flushed by this call. Return 0 on success, -1 on 81 * unrecoverable error. 82 */ 83 int dispatch_flush(dispatch_t *, channel_id_t chan, int max_msgs); 84 85 /** 86 * Function callback type used to alert some other module when a channel's 87 * queue changes from empty to nonempty. 88 * 89 * Ex 1: To cause messages to be processed immediately on-stack, this callback 90 * should invoke dispatch_flush() directly. 91 * 92 * Ex 2: To cause messages to be processed very soon, from the event queue, 93 * this callback should schedule an event callback to run dispatch_flush(). 94 * 95 * Ex 3: To cause messages to be processed periodically, this function should 96 * do nothing, and a periodic event should invoke dispatch_flush(). 97 **/ 98 typedef void (*dispatch_alertfn_t)(struct dispatch_t *, 99 channel_id_t, void *); 100 101 int dispatch_set_alert_fn(dispatch_t *d, channel_id_t chan, 102 dispatch_alertfn_t fn, void *userdata); 103 104 #define dispatch_free_msg(d,msg) \ 105 STMT_BEGIN { \ 106 msg_t **msg_tmp_ptr__ = &(msg); \ 107 dispatch_free_msg_((d), *msg_tmp_ptr__); \ 108 *msg_tmp_ptr__= NULL; \ 109 } STMT_END 110 void dispatch_free_msg_(const dispatch_t *d, msg_t *msg); 111 112 char *dispatch_fmt_msg_data(const dispatch_t *d, const msg_t *msg); 113 114 #endif /* !defined(TOR_DISPATCH_H) */ 115