]>
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 | ||
24a58196 | 10 | #include "frrevent.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 { | |
e6685141 | 29 | struct event *thread; |
afd0f10d | 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 | ({ \ | |
5163a1c5 | 62 | static const struct xref_eventsched _xref __attribute__( \ |
2ccccdf5 | 63 | (used)) = { \ |
5163a1c5 | 64 | .xref = XREF_INIT(XREFT_EVENTSCHED, NULL, __func__), \ |
60a3efec DL |
65 | .funcname = #f, \ |
66 | .dest = #d, \ | |
2ccccdf5 | 67 | .event_type = EVENT_##type, \ |
60a3efec DL |
68 | }; \ |
69 | XREF_LINK(_xref.xref); \ | |
70 | call; \ | |
2ccccdf5 | 71 | }) /* end */ |
b6116506 | 72 | |
f3cd305f | 73 | /* core event registration, one of these 2 macros should be used */ |
907a2395 | 74 | #define frrzmq_event_add_read_msg(m, f, e, a, z, d) \ |
60a3efec | 75 | _xref_zmq_a(READ, f, d, \ |
907a2395 | 76 | _frrzmq_event_add_read(&_xref, m, f, NULL, e, a, z, d)) |
60a3efec | 77 | |
907a2395 | 78 | #define frrzmq_event_add_read_part(m, f, e, a, z, d) \ |
60a3efec | 79 | _xref_zmq_a(READ, f, d, \ |
907a2395 | 80 | _frrzmq_event_add_read(&_xref, m, NULL, f, e, a, z, d)) |
60a3efec | 81 | |
907a2395 | 82 | #define frrzmq_event_add_write_msg(m, f, e, a, z, d) \ |
60a3efec | 83 | _xref_zmq_a(WRITE, f, d, \ |
907a2395 | 84 | _frrzmq_event_add_write(&_xref, m, f, e, a, z, d)) |
b6116506 | 85 | |
afd0f10d | 86 | struct cb_core; |
b6116506 DL |
87 | struct frrzmq_cb; |
88 | ||
afd0f10d | 89 | /* Set up a POLLIN or POLLOUT notification to be called from the libfrr main |
90 | * loop. This has the following properties: | |
f3cd305f DL |
91 | * |
92 | * - since ZeroMQ works with edge triggered notifications, it will loop and | |
93 | * dispatch as many events as ZeroMQ has pending at the time libfrr calls | |
94 | * into this code | |
95 | * - due to this looping (which means it non-single-issue), the callback is | |
96 | * also persistent. Do _NOT_ re-register the event inside of your | |
97 | * callback function. | |
98 | * - either msgfunc or partfunc will be called (only one can be specified) | |
99 | * - msgfunc is called once for each incoming message | |
100 | * - if partfunc is specified, the message is read and partfunc is called | |
101 | * for each ZeroMQ multi-part subpart. Note that you can't send replies | |
102 | * before all parts have been read because that violates the ZeroMQ FSM. | |
afd0f10d | 103 | * - write version doesn't allow for partial callback, you must handle the |
104 | * whole message (all parts) in msgfunc callback | |
f3cd305f DL |
105 | * - you can safely cancel the callback from within itself |
106 | * - installing a callback will check for pending events (ZMQ_EVENTS) and | |
107 | * may schedule the event to run as soon as libfrr is back in its main | |
108 | * loop. | |
afd0f10d | 109 | */ |
907a2395 | 110 | extern int |
5163a1c5 | 111 | _frrzmq_event_add_read(const struct xref_eventsched *xref, |
cd9d0537 | 112 | struct event_loop *master, |
907a2395 DS |
113 | void (*msgfunc)(void *arg, void *zmqsock), |
114 | void (*partfunc)(void *arg, void *zmqsock, | |
115 | zmq_msg_t *msg, unsigned partnum), | |
116 | void (*errfunc)(void *arg, void *zmqsock), void *arg, | |
117 | void *zmqsock, struct frrzmq_cb **cb); | |
5163a1c5 | 118 | extern int _frrzmq_event_add_write(const struct xref_eventsched *xref, |
cd9d0537 | 119 | struct event_loop *master, |
907a2395 DS |
120 | void (*msgfunc)(void *arg, void *zmqsock), |
121 | void (*errfunc)(void *arg, void *zmqsock), | |
122 | void *arg, void *zmqsock, | |
123 | struct frrzmq_cb **cb); | |
afd0f10d | 124 | |
125 | extern void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core); | |
126 | ||
127 | /* | |
128 | * http://api.zeromq.org/4-2:zmq-getsockopt#toc10 | |
f3cd305f | 129 | * |
afd0f10d | 130 | * As the descriptor is edge triggered, applications must update the state of |
131 | * ZMQ_EVENTS after each invocation of zmq_send or zmq_recv.To be more explicit: | |
132 | * after calling zmq_send the socket may become readable (and vice versa) | |
133 | * without triggering a read event on the file descriptor. | |
f3cd305f | 134 | */ |
afd0f10d | 135 | extern void frrzmq_check_events(struct frrzmq_cb **cbp, struct cb_core *core, |
136 | int event); | |
b6116506 | 137 | |
5e244469 RW |
138 | #ifdef __cplusplus |
139 | } | |
140 | #endif | |
141 | ||
b6116506 | 142 | #endif /* _FRRZMQ_H */ |