]> git.proxmox.com Git - mirror_frr.git/blame - lib/frr_zmq.h
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / frr_zmq.h
CommitLineData
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
14extern "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 */
28struct 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 40struct 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
55extern void *frrzmq_context;
56
afd0f10d 57extern void frrzmq_init(void);
58extern 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 86struct cb_core;
b6116506
DL
87struct 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 110extern 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 118extern 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
125extern 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 135extern 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 */