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