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 26 #ifdef __cplusplus 27 extern "C" { 28 #endif 29 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 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 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 */ 65 extern void *frrzmq_context; 66 67 extern void frrzmq_init(void); 68 extern void frrzmq_finish(void); 69 70 #define debugargdef const char *funcname, const char *schedfrom, int fromln 71 72 /* core event registration, one of these 2 macros should be used */ 73 #define frrzmq_thread_add_read_msg(m, f, e, a, z, d) \ 74 funcname_frrzmq_thread_add_read(m, f, NULL, e, a, z, d, #f, __FILE__, \ 75 __LINE__) 76 #define frrzmq_thread_add_read_part(m, f, e, a, z, d) \ 77 funcname_frrzmq_thread_add_read(m, NULL, f, e, a, z, d, #f, __FILE__, \ 78 __LINE__) 79 #define frrzmq_thread_add_write_msg(m, f, e, a, z, d) \ 80 funcname_frrzmq_thread_add_write(m, f, e, a, z, d, #f, __FILE__, \ 81 __LINE__) 82 83 struct cb_core; 84 struct frrzmq_cb; 85 86 /* Set up a POLLIN or POLLOUT notification to be called from the libfrr main 87 * loop. This has the following properties: 88 * 89 * - since ZeroMQ works with edge triggered notifications, it will loop and 90 * dispatch as many events as ZeroMQ has pending at the time libfrr calls 91 * into this code 92 * - due to this looping (which means it non-single-issue), the callback is 93 * also persistent. Do _NOT_ re-register the event inside of your 94 * callback function. 95 * - either msgfunc or partfunc will be called (only one can be specified) 96 * - msgfunc is called once for each incoming message 97 * - if partfunc is specified, the message is read and partfunc is called 98 * for each ZeroMQ multi-part subpart. Note that you can't send replies 99 * before all parts have been read because that violates the ZeroMQ FSM. 100 * - write version doesn't allow for partial callback, you must handle the 101 * whole message (all parts) in msgfunc callback 102 * - you can safely cancel the callback from within itself 103 * - installing a callback will check for pending events (ZMQ_EVENTS) and 104 * may schedule the event to run as soon as libfrr is back in its main 105 * loop. 106 */ 107 extern int funcname_frrzmq_thread_add_read( 108 struct thread_master *master, void (*msgfunc)(void *arg, void *zmqsock), 109 void (*partfunc)(void *arg, void *zmqsock, zmq_msg_t *msg, 110 unsigned partnum), 111 void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock, 112 struct frrzmq_cb **cb, debugargdef); 113 extern int funcname_frrzmq_thread_add_write( 114 struct thread_master *master, void (*msgfunc)(void *arg, void *zmqsock), 115 void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock, 116 struct frrzmq_cb **cb, debugargdef); 117 118 extern void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core); 119 120 /* 121 * http://api.zeromq.org/4-2:zmq-getsockopt#toc10 122 * 123 * As the descriptor is edge triggered, applications must update the state of 124 * ZMQ_EVENTS after each invocation of zmq_send or zmq_recv.To be more explicit: 125 * after calling zmq_send the socket may become readable (and vice versa) 126 * without triggering a read event on the file descriptor. 127 */ 128 extern void frrzmq_check_events(struct frrzmq_cb **cbp, struct cb_core *core, 129 int event); 130 131 #ifdef __cplusplus 132 } 133 #endif 134 135 #endif /* _FRRZMQ_H */ 136