]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
b6116506 DL |
2 | /* |
3 | * libzebra ZeroMQ bindings | |
4 | * Copyright (C) 2015 David Lamparter | |
b6116506 DL |
5 | */ |
6 | ||
7 | #ifndef _FRRZMQ_H | |
8 | #define _FRRZMQ_H | |
9 | ||
cb37cb33 | 10 | #include "event.h" |
b6116506 DL |
11 | #include <zmq.h> |
12 | ||
5e244469 RW |
13 | #ifdef __cplusplus |
14 | extern "C" { | |
15 | #endif | |
16 | ||
f3cd305f DL |
17 | /* linking/packaging note: this is a separate library that needs to be |
18 | * linked into any daemon/library/module that wishes to use its | |
19 | * functionality. The purpose of this is to encapsulate the libzmq | |
20 | * dependency and not make libfrr/FRR itself depend on libzmq. | |
21 | * | |
22 | * libfrrzmq should be put in LDFLAGS/LIBADD *before* either libfrr or | |
23 | * libzmq, and both of these should always be listed, e.g. | |
24 | * foo_LDFLAGS = libfrrzmq.la libfrr.la $(ZEROMQ_LIBS) | |
25 | */ | |
26 | ||
afd0f10d | 27 | /* callback integration */ |
28 | struct cb_core { | |
29 | struct thread *thread; | |
30 | void *arg; | |
31 | ||
32 | bool cancelled; | |
33 | ||
34 | void (*cb_msg)(void *arg, void *zmqsock); | |
35 | void (*cb_part)(void *arg, void *zmqsock, zmq_msg_t *msg, | |
36 | unsigned partnum); | |
37 | void (*cb_error)(void *arg, void *zmqsock); | |
38 | }; | |
8fd5502b | 39 | |
afd0f10d | 40 | struct frrzmq_cb { |
41 | void *zmqsock; | |
42 | int fd; | |
43 | ||
8fd5502b MS |
44 | bool in_cb; /* This context is in a read or write callback. */ |
45 | ||
afd0f10d | 46 | struct cb_core read; |
47 | struct cb_core write; | |
48 | }; | |
49 | ||
f3cd305f DL |
50 | /* libzmq's context |
51 | * | |
52 | * this is mostly here as a convenience, it has IPv6 enabled but nothing | |
53 | * else is tied to it; you can use a separate context without problems | |
54 | */ | |
b6116506 DL |
55 | extern void *frrzmq_context; |
56 | ||
afd0f10d | 57 | extern void frrzmq_init(void); |
58 | extern void frrzmq_finish(void); | |
b6116506 | 59 | |
60a3efec DL |
60 | #define _xref_zmq_a(type, f, d, call) \ |
61 | ({ \ | |
62 | static const struct xref_threadsched _xref \ | |
63 | __attribute__((used)) = { \ | |
64 | .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \ | |
65 | .funcname = #f, \ | |
66 | .dest = #d, \ | |
67 | .thread_type = THREAD_ ## type, \ | |
68 | }; \ | |
69 | XREF_LINK(_xref.xref); \ | |
70 | call; \ | |
71 | }) \ | |
72 | /* end */ | |
b6116506 | 73 | |
f3cd305f | 74 | /* core event registration, one of these 2 macros should be used */ |
afd0f10d | 75 | #define frrzmq_thread_add_read_msg(m, f, e, a, z, d) \ |
60a3efec DL |
76 | _xref_zmq_a(READ, f, d, \ |
77 | _frrzmq_thread_add_read(&_xref, m, f, NULL, e, a, z, d)) | |
78 | ||
afd0f10d | 79 | #define frrzmq_thread_add_read_part(m, f, e, a, z, d) \ |
60a3efec DL |
80 | _xref_zmq_a(READ, f, d, \ |
81 | _frrzmq_thread_add_read(&_xref, m, NULL, f, e, a, z, d)) | |
82 | ||
afd0f10d | 83 | #define frrzmq_thread_add_write_msg(m, f, e, a, z, d) \ |
60a3efec DL |
84 | _xref_zmq_a(WRITE, f, d, \ |
85 | _frrzmq_thread_add_write(&_xref, m, f, e, a, z, d)) | |
b6116506 | 86 | |
afd0f10d | 87 | struct cb_core; |
b6116506 DL |
88 | struct frrzmq_cb; |
89 | ||
afd0f10d | 90 | /* Set up a POLLIN or POLLOUT notification to be called from the libfrr main |
91 | * loop. This has the following properties: | |
f3cd305f DL |
92 | * |
93 | * - since ZeroMQ works with edge triggered notifications, it will loop and | |
94 | * dispatch as many events as ZeroMQ has pending at the time libfrr calls | |
95 | * into this code | |
96 | * - due to this looping (which means it non-single-issue), the callback is | |
97 | * also persistent. Do _NOT_ re-register the event inside of your | |
98 | * callback function. | |
99 | * - either msgfunc or partfunc will be called (only one can be specified) | |
100 | * - msgfunc is called once for each incoming message | |
101 | * - if partfunc is specified, the message is read and partfunc is called | |
102 | * for each ZeroMQ multi-part subpart. Note that you can't send replies | |
103 | * before all parts have been read because that violates the ZeroMQ FSM. | |
afd0f10d | 104 | * - write version doesn't allow for partial callback, you must handle the |
105 | * whole message (all parts) in msgfunc callback | |
f3cd305f DL |
106 | * - you can safely cancel the callback from within itself |
107 | * - installing a callback will check for pending events (ZMQ_EVENTS) and | |
108 | * may schedule the event to run as soon as libfrr is back in its main | |
109 | * loop. | |
afd0f10d | 110 | */ |
60a3efec DL |
111 | extern int _frrzmq_thread_add_read( |
112 | const struct xref_threadsched *xref, struct thread_master *master, | |
113 | void (*msgfunc)(void *arg, void *zmqsock), | |
afd0f10d | 114 | void (*partfunc)(void *arg, void *zmqsock, zmq_msg_t *msg, |
115 | unsigned partnum), | |
116 | void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock, | |
60a3efec DL |
117 | struct frrzmq_cb **cb); |
118 | extern int _frrzmq_thread_add_write( | |
119 | const struct xref_threadsched *xref, struct thread_master *master, | |
120 | void (*msgfunc)(void *arg, void *zmqsock), | |
afd0f10d | 121 | void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock, |
60a3efec | 122 | struct frrzmq_cb **cb); |
afd0f10d | 123 | |
124 | extern void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core); | |
125 | ||
126 | /* | |
127 | * http://api.zeromq.org/4-2:zmq-getsockopt#toc10 | |
f3cd305f | 128 | * |
afd0f10d | 129 | * As the descriptor is edge triggered, applications must update the state of |
130 | * ZMQ_EVENTS after each invocation of zmq_send or zmq_recv.To be more explicit: | |
131 | * after calling zmq_send the socket may become readable (and vice versa) | |
132 | * without triggering a read event on the file descriptor. | |
f3cd305f | 133 | */ |
afd0f10d | 134 | extern void frrzmq_check_events(struct frrzmq_cb **cbp, struct cb_core *core, |
135 | int event); | |
b6116506 | 136 | |
5e244469 RW |
137 | #ifdef __cplusplus |
138 | } | |
139 | #endif | |
140 | ||
b6116506 | 141 | #endif /* _FRRZMQ_H */ |