]>
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 | ||
f3cd305f DL |
26 | /* linking/packaging note: this is a separate library that needs to be |
27 | * linked into any daemon/library/module that wishes to use its | |
28 | * functionality. The purpose of this is to encapsulate the libzmq | |
29 | * dependency and not make libfrr/FRR itself depend on libzmq. | |
30 | * | |
31 | * libfrrzmq should be put in LDFLAGS/LIBADD *before* either libfrr or | |
32 | * libzmq, and both of these should always be listed, e.g. | |
33 | * foo_LDFLAGS = libfrrzmq.la libfrr.la $(ZEROMQ_LIBS) | |
34 | */ | |
35 | ||
afd0f10d | 36 | /* callback integration */ |
37 | struct cb_core { | |
38 | struct thread *thread; | |
39 | void *arg; | |
40 | ||
41 | bool cancelled; | |
42 | ||
43 | void (*cb_msg)(void *arg, void *zmqsock); | |
44 | void (*cb_part)(void *arg, void *zmqsock, zmq_msg_t *msg, | |
45 | unsigned partnum); | |
46 | void (*cb_error)(void *arg, void *zmqsock); | |
47 | }; | |
48 | struct frrzmq_cb { | |
49 | void *zmqsock; | |
50 | int fd; | |
51 | ||
52 | struct cb_core read; | |
53 | struct cb_core write; | |
54 | }; | |
55 | ||
f3cd305f DL |
56 | /* libzmq's context |
57 | * | |
58 | * this is mostly here as a convenience, it has IPv6 enabled but nothing | |
59 | * else is tied to it; you can use a separate context without problems | |
60 | */ | |
b6116506 DL |
61 | extern void *frrzmq_context; |
62 | ||
afd0f10d | 63 | extern void frrzmq_init(void); |
64 | extern void frrzmq_finish(void); | |
b6116506 DL |
65 | |
66 | #define debugargdef const char *funcname, const char *schedfrom, int fromln | |
67 | ||
f3cd305f | 68 | /* core event registration, one of these 2 macros should be used */ |
afd0f10d | 69 | #define frrzmq_thread_add_read_msg(m, f, e, a, z, d) \ |
70 | funcname_frrzmq_thread_add_read(m, f, NULL, e, a, z, d, #f, __FILE__, \ | |
71 | __LINE__) | |
72 | #define frrzmq_thread_add_read_part(m, f, e, a, z, d) \ | |
73 | funcname_frrzmq_thread_add_read(m, NULL, f, e, a, z, d, #f, __FILE__, \ | |
74 | __LINE__) | |
75 | #define frrzmq_thread_add_write_msg(m, f, e, a, z, d) \ | |
76 | funcname_frrzmq_thread_add_write(m, f, e, a, z, d, #f, __FILE__, \ | |
77 | __LINE__) | |
b6116506 | 78 | |
afd0f10d | 79 | struct cb_core; |
b6116506 DL |
80 | struct frrzmq_cb; |
81 | ||
afd0f10d | 82 | /* Set up a POLLIN or POLLOUT notification to be called from the libfrr main |
83 | * loop. This has the following properties: | |
f3cd305f DL |
84 | * |
85 | * - since ZeroMQ works with edge triggered notifications, it will loop and | |
86 | * dispatch as many events as ZeroMQ has pending at the time libfrr calls | |
87 | * into this code | |
88 | * - due to this looping (which means it non-single-issue), the callback is | |
89 | * also persistent. Do _NOT_ re-register the event inside of your | |
90 | * callback function. | |
91 | * - either msgfunc or partfunc will be called (only one can be specified) | |
92 | * - msgfunc is called once for each incoming message | |
93 | * - if partfunc is specified, the message is read and partfunc is called | |
94 | * for each ZeroMQ multi-part subpart. Note that you can't send replies | |
95 | * before all parts have been read because that violates the ZeroMQ FSM. | |
afd0f10d | 96 | * - write version doesn't allow for partial callback, you must handle the |
97 | * whole message (all parts) in msgfunc callback | |
f3cd305f DL |
98 | * - you can safely cancel the callback from within itself |
99 | * - installing a callback will check for pending events (ZMQ_EVENTS) and | |
100 | * may schedule the event to run as soon as libfrr is back in its main | |
101 | * loop. | |
afd0f10d | 102 | */ |
103 | extern int funcname_frrzmq_thread_add_read( | |
104 | struct thread_master *master, void (*msgfunc)(void *arg, void *zmqsock), | |
105 | void (*partfunc)(void *arg, void *zmqsock, zmq_msg_t *msg, | |
106 | unsigned partnum), | |
107 | void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock, | |
108 | struct frrzmq_cb **cb, debugargdef); | |
109 | extern int funcname_frrzmq_thread_add_write( | |
110 | struct thread_master *master, void (*msgfunc)(void *arg, void *zmqsock), | |
111 | void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock, | |
112 | struct frrzmq_cb **cb, debugargdef); | |
113 | ||
114 | extern void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core); | |
115 | ||
116 | /* | |
117 | * http://api.zeromq.org/4-2:zmq-getsockopt#toc10 | |
f3cd305f | 118 | * |
afd0f10d | 119 | * As the descriptor is edge triggered, applications must update the state of |
120 | * ZMQ_EVENTS after each invocation of zmq_send or zmq_recv.To be more explicit: | |
121 | * after calling zmq_send the socket may become readable (and vice versa) | |
122 | * without triggering a read event on the file descriptor. | |
f3cd305f | 123 | */ |
afd0f10d | 124 | extern void frrzmq_check_events(struct frrzmq_cb **cbp, struct cb_core *core, |
125 | int event); | |
b6116506 DL |
126 | |
127 | #endif /* _FRRZMQ_H */ |