2 * Copyright (c) 2014-2015 Timo Teräs
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
11 #include <sys/socket.h>
19 const char *nhrp_event_socket_path;
20 struct nhrp_reqid_pool nhrp_event_reqid;
22 struct event_manager {
23 struct thread *t_reconnect, *t_read, *t_write;
25 struct zbuf_queue obuf;
27 uint8_t ibuf_data[4*1024];
30 static int evmgr_reconnect(struct thread *t);
32 static void evmgr_connection_error(struct event_manager *evmgr)
34 THREAD_OFF(evmgr->t_read);
35 THREAD_OFF(evmgr->t_write);
36 zbuf_reset(&evmgr->ibuf);
37 zbufq_reset(&evmgr->obuf);
42 if (nhrp_event_socket_path)
43 THREAD_TIMER_MSEC_ON(master, evmgr->t_reconnect, evmgr_reconnect,
47 static void evmgr_recv_message(struct event_manager *evmgr, struct zbuf *zb)
52 char buf[256], result[64] = "";
54 while (zbuf_may_pull_until(zb, "\n", &zl)) {
55 len = zbuf_used(&zl) - 1;
56 if (len >= sizeof(buf)-1)
58 memcpy(buf, zbuf_pulln(&zl, len), len);
61 debugf(NHRP_DEBUG_EVENT, "evmgr: msg: %s", buf);
62 sscanf(buf, "eventid=%d", &eventid);
63 sscanf(buf, "result=%63s", result);
65 debugf(NHRP_DEBUG_EVENT, "evmgr: received: eventid=%d result=%s", eventid, result);
66 if (eventid && result[0]) {
67 struct nhrp_reqid *r = nhrp_reqid_lookup(&nhrp_event_reqid, eventid);
68 if (r) r->cb(r, result);
72 static int evmgr_read(struct thread *t)
74 struct event_manager *evmgr = THREAD_ARG(t);
75 struct zbuf *ibuf = &evmgr->ibuf;
79 if (zbuf_read(ibuf, evmgr->fd, (size_t) -1) < 0) {
80 evmgr_connection_error(evmgr);
84 /* Process all messages in buffer */
85 while (zbuf_may_pull_until(ibuf, "\n\n", &msg))
86 evmgr_recv_message(evmgr, &msg);
88 THREAD_READ_ON(master, evmgr->t_read, evmgr_read, evmgr, evmgr->fd);
92 static int evmgr_write(struct thread *t)
94 struct event_manager *evmgr = THREAD_ARG(t);
97 evmgr->t_write = NULL;
98 r = zbufq_write(&evmgr->obuf, evmgr->fd);
100 THREAD_WRITE_ON(master, evmgr->t_write, evmgr_write, evmgr, evmgr->fd);
102 evmgr_connection_error(evmgr);
108 static void evmgr_hexdump(struct zbuf *zb, const uint8_t *val, size_t vallen)
110 static const char xd[] = "0123456789abcdef";
114 ptr = zbuf_pushn(zb, 2*vallen);
117 for (i = 0; i < vallen; i++) {
119 *(ptr++) = xd[b >> 4];
120 *(ptr++) = xd[b & 0xf];
124 static void evmgr_put(struct zbuf *zb, const char *fmt, ...)
126 const char *pos, *nxt, *str;
128 const union sockunion *su;
133 for (pos = fmt; (nxt = strchr(pos, '%')) != NULL; pos = nxt + 2) {
134 zbuf_put(zb, pos, nxt-pos);
140 zb->tail += snprintf((char *) zb->tail, zbuf_tailroom(zb), "%u", va_arg(va, uint32_t));
143 str = va_arg(va, const char *);
144 zbuf_put(zb, str, strlen(str));
147 su = va_arg(va, const union sockunion *);
148 if (sockunion2str(su, (char *) zb->tail, zbuf_tailroom(zb)))
149 zb->tail += strlen((char *) zb->tail);
154 bin = va_arg(va, const uint8_t *);
155 len = va_arg(va, int);
156 evmgr_hexdump(zb, bin, len);
161 zbuf_put(zb, pos, strlen(pos));
164 static void evmgr_submit(struct event_manager *evmgr, struct zbuf *obuf)
170 zbuf_put(obuf, "\n", 1);
171 zbufq_queue(&evmgr->obuf, obuf);
173 THREAD_WRITE_ON(master, evmgr->t_write, evmgr_write, evmgr, evmgr->fd);
176 static int evmgr_reconnect(struct thread *t)
178 struct event_manager *evmgr = THREAD_ARG(t);
181 evmgr->t_reconnect = NULL;
182 if (evmgr->fd >= 0 || !nhrp_event_socket_path) return 0;
184 fd = sock_open_unix(nhrp_event_socket_path);
186 zlog_warn("%s: failure connecting nhrp-event socket: %s",
187 __PRETTY_FUNCTION__, strerror(errno));
188 zbufq_reset(&evmgr->obuf);
189 THREAD_TIMER_ON(master, evmgr->t_reconnect, evmgr_reconnect, evmgr, 10);
193 zlog_info("Connected to Event Manager");
195 THREAD_READ_ON(master, evmgr->t_read, evmgr_read, evmgr, evmgr->fd);
200 static struct event_manager evmgr_connection;
202 void evmgr_init(void)
204 struct event_manager *evmgr = &evmgr_connection;
207 zbuf_init(&evmgr->ibuf, evmgr->ibuf_data, sizeof(evmgr->ibuf_data), 0);
208 zbufq_init(&evmgr->obuf);
209 THREAD_TIMER_MSEC_ON(master, evmgr->t_reconnect, evmgr_reconnect, evmgr, 10);
212 void evmgr_set_socket(const char *socket)
214 if (nhrp_event_socket_path) {
215 free((char *) nhrp_event_socket_path);
216 nhrp_event_socket_path = NULL;
219 nhrp_event_socket_path = strdup(socket);
220 evmgr_connection_error(&evmgr_connection);
223 void evmgr_terminate(void)
227 void evmgr_notify(const char *name, struct nhrp_cache *c, void (*cb)(struct nhrp_reqid *, void *))
229 struct event_manager *evmgr = &evmgr_connection;
231 struct nhrp_interface *nifp = c->ifp->info;
233 afi_t afi = family2afi(sockunion_family(&c->remote_addr));
235 if (!nhrp_event_socket_path) {
236 cb(&c->eventid, (void*) "accept");
240 debugf(NHRP_DEBUG_EVENT, "evmgr: sending event %s", name);
242 vc = c->new.peer ? c->new.peer->vc : NULL;
243 zb = zbuf_alloc(1024 + (vc ? (vc->local.certlen + vc->remote.certlen) * 2 : 0));
246 nhrp_reqid_free(&nhrp_event_reqid, &c->eventid);
249 nhrp_reqid_alloc(&nhrp_event_reqid, &c->eventid, cb));
260 nhrp_cache_type_str[c->new.type],
261 nhrp_cache_type_str[c->cur.type],
262 (unsigned int) nhrp_cache_counts[NHRP_CACHE_NHS],
264 &nifp->afi[afi].addr);
274 c->new.peer->requested ? "yes" : "no",
276 vc->local.cert, vc->local.certlen,
277 &c->remote_addr, &vc->remote.nbma,
278 vc->remote.cert, vc->remote.certlen);
281 evmgr_submit(evmgr, zb);