1.. highlight:: c
2
3Hooks
4=====
5
6Libfrr provides type-safe subscribable hook points where other pieces of
7code can add one or more callback functions.  "type-safe" in this case
8applies to the function pointers used for subscriptions.  The
9implementations checks (at compile-time) whether a callback to be added has
10the appropriate function signature (parameters) for the hook.
11
12Example:
13
14.. code-block:: c
15   :caption: mydaemon.h
16
17   #include "hook.h"
18   DECLARE_HOOK(some_update_event, (struct eventinfo *info), (info))
19
20.. code-block:: c
21   :caption: mydaemon.c
22
23   #include "mydaemon.h"
24   DEFINE_HOOK(some_update_event, (struct eventinfo *info), (info))
25   ...
26   hook_call(some_update_event, info);
27
28.. code-block:: c
29   :caption: mymodule.c
30
31   #include "mydaemon.h"
32   static int event_handler(struct eventinfo *info);
33   ...
34   hook_register(some_update_event, event_handler);
35
36Do not use parameter names starting with "hook", these can collide with
37names used by the hook code itself.
38
39
40Return values
41-------------
42
43Callbacks to be placed on hooks always return "int" for now;  hook_call will
44sum up the return values from each called function.  (The default is 0 if no
45callbacks are registered.)
46
47There are no pre-defined semantics for the value, in most cases it is
48ignored.  For success/failure indication, 0 should be success, and
49handlers should make sure to only return 0 or 1 (not -1 or other values).
50
51There is no built-in way to abort executing a chain after a failure of one
52of the callbacks.  If this is needed, the hook can use an extra
53``bool *aborted`` argument.
54
55
56Priorities
57----------
58
59Hooks support a "priority" value for ordering registered calls
60relative to each other.  The priority is a signed integer where lower
61values are called earlier.  There are also "Koohs", which is hooks with
62reverse priority ordering (for cleanup/deinit hooks, so you can use the
63same priority value).
64
65Recommended priority value ranges are:
66
67======================== ===================================================
68Range                    Usage
69------------------------ ---------------------------------------------------
70 -999 ...     0 ...  999 main executable / daemon, or library
71
72-1999 ... -1000          modules registering calls that should run before
73                         the daemon's bits
74
751000 ... 1999            modules' calls that should run after daemon's
76                         (includes default value: 1000)
77======================== ===================================================
78
79Note: the default value is 1000, based on the following 2 expectations:
80
81- most hook_register() usage will be in loadable modules
82- usage of hook_register() in the daemon itself may need relative ordering
83  to itself, making an explicit value the expected case
84
85The priority value is passed as extra argument on hook_register_prio() /
86hook_register_arg_prio().  Whether a hook runs in reverse is determined
87solely by the code defining / calling the hook.  (DECLARE_KOOH is actually
88the same thing as DECLARE_HOOK, it's just there to make it obvious.)
89
90
91Definition
92----------
93
94.. c:macro:: DECLARE_HOOK(name, arglist, passlist)
95.. c:macro:: DECLARE_KOOH(name, arglist, passlist)
96
97   :param name: Name of the hook to be defined
98   :param arglist: Function definition style parameter list in braces.
99   :param passlist: List of the same parameters without their types.
100
101   Note:  the second and third macro args must be the hook function's
102   parameter list, with the same names for each parameter.  The second
103   macro arg is with types (used for defining things), the third arg is
104   just the names (used for passing along parameters).
105
106   This macro must be placed in a header file;  this header file must be
107   included to register a callback on the hook.
108
109   Examples:
110
111   .. code-block:: c
112
113      DECLARE_HOOK(foo, (), ())
114      DECLARE_HOOK(bar, (int arg), (arg))
115      DECLARE_HOOK(baz, (const void *x, in_addr_t y), (x, y))
116
117.. c:macro:: DEFINE_HOOK(name, arglist, passlist)
118
119   Implements an hook.  Each ``DECLARE_HOOK`` must have be accompanied by
120   exactly one ``DEFINE_HOOK``, which needs to be placed in a source file.
121   **The hook can only be called from this source file.**  This is intentional
122   to avoid overloading and/or misusing hooks for distinct purposes.
123
124   The compiled source file will include a global symbol with the name of the
125   hook prefixed by `_hook_`.  Trying to register a callback for a hook that
126   doesn't exist will therefore result in a linker error, or a module
127   load-time error for dynamic modules.
128
129.. c:macro:: DEFINE_KOOH(name, arglist, passlist)
130
131   Same as ``DEFINE_HOOK``, but the sense of priorities / order of callbacks
132   is reversed.  This should be used for cleanup hooks.
133
134.. c:function:: int hook_call(name, ...)
135
136   Calls the specified named hook.  Parameters to the hook are passed right
137   after the hook name, e.g.:
138
139   .. code-block:: c
140
141      hook_call(foo);
142      hook_call(bar, 0);
143      hook_call(baz, NULL, INADDR_ANY);
144
145   Returns the sum of return values from all callbacks.  The ``DEFINE_HOOK``
146   statement for the hook must be placed in the file before any ``hook_call``
147   use of the hook.
148
149
150Callback registration
151---------------------
152
153.. c:function:: void hook_register(name, int (*callback)(...))
154.. c:function:: void hook_register_prio(name, int priority, int (*callback)(...))
155.. c:function:: void hook_register_arg(name, int (*callback)(void *arg, ...), void *arg)
156.. c:function:: void hook_register_arg_prio(name, int priority, int (*callback)(void *arg, ...), void *arg)
157
158   Register a callback with an hook.  If the caller needs to pass an extra
159   argument to the callback, the _arg variant can be used and the extra
160   parameter will be passed as first argument to the callback.  There is no
161   typechecking for this argument.
162
163   The priority value is used as described above.  The variants without a
164   priority parameter use 1000 as priority value.
165
166.. c:function:: void hook_unregister(name, int (*callback)(...))
167.. c:function:: void hook_unregister_arg(name, int (*callback)(void *arg, ...), void *arg)
168
169   Removes a previously registered callback from a hook.  Note that there
170   is no _prio variant of these calls.  The priority value is only used during
171   registration.
172