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
= strdup(socket
);
217 evmgr_connection_error(&evmgr_connection
);
220 void evmgr_terminate(void)
224 void evmgr_notify(const char *name
, struct nhrp_cache
*c
, void (*cb
)(struct nhrp_reqid
*, void *))
226 struct event_manager
*evmgr
= &evmgr_connection
;
228 struct nhrp_interface
*nifp
= c
->ifp
->info
;
230 afi_t afi
= family2afi(sockunion_family(&c
->remote_addr
));
232 if (!nhrp_event_socket_path
) {
233 cb(&c
->eventid
, (void*) "accept");
237 debugf(NHRP_DEBUG_EVENT
, "evmgr: sending event %s", name
);
239 vc
= c
->new.peer
? c
->new.peer
->vc
: NULL
;
240 zb
= zbuf_alloc(1024 + (vc
? (vc
->local
.certlen
+ vc
->remote
.certlen
) * 2 : 0));
243 nhrp_reqid_free(&nhrp_event_reqid
, &c
->eventid
);
246 nhrp_reqid_alloc(&nhrp_event_reqid
, &c
->eventid
, cb
));
257 nhrp_cache_type_str
[c
->new.type
],
258 nhrp_cache_type_str
[c
->cur
.type
],
259 (unsigned int) nhrp_cache_counts
[NHRP_CACHE_NHS
],
261 &nifp
->afi
[afi
].addr
);
271 c
->new.peer
->requested
? "yes" : "no",
273 vc
->local
.cert
, vc
->local
.certlen
,
274 &c
->remote_addr
, &vc
->remote
.nbma
,
275 vc
->remote
.cert
, vc
->remote
.certlen
);
278 evmgr_submit(evmgr
, zb
);