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