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_add_timer_msec(master
, evmgr_reconnect
, evmgr
, 10,
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 if (sscanf(buf
, "eventid=%d", &eventid
) != 1)
64 if (sscanf(buf
, "result=%63s", result
) != 1)
67 debugf(NHRP_DEBUG_EVENT
, "evmgr: received: eventid=%d result=%s", eventid
, result
);
68 if (eventid
&& result
[0]) {
69 struct nhrp_reqid
*r
= nhrp_reqid_lookup(&nhrp_event_reqid
, eventid
);
70 if (r
) r
->cb(r
, result
);
74 static int evmgr_read(struct thread
*t
)
76 struct event_manager
*evmgr
= THREAD_ARG(t
);
77 struct zbuf
*ibuf
= &evmgr
->ibuf
;
81 if (zbuf_read(ibuf
, evmgr
->fd
, (size_t) -1) < 0) {
82 evmgr_connection_error(evmgr
);
86 /* Process all messages in buffer */
87 while (zbuf_may_pull_until(ibuf
, "\n\n", &msg
))
88 evmgr_recv_message(evmgr
, &msg
);
90 thread_add_read(master
, evmgr_read
, evmgr
, evmgr
->fd
, &evmgr
->t_read
);
94 static int evmgr_write(struct thread
*t
)
96 struct event_manager
*evmgr
= THREAD_ARG(t
);
99 evmgr
->t_write
= NULL
;
100 r
= zbufq_write(&evmgr
->obuf
, evmgr
->fd
);
102 thread_add_write(master
, evmgr_write
, evmgr
, evmgr
->fd
,
105 evmgr_connection_error(evmgr
);
111 static void evmgr_hexdump(struct zbuf
*zb
, const uint8_t *val
, size_t vallen
)
113 static const char xd
[] = "0123456789abcdef";
117 ptr
= zbuf_pushn(zb
, 2*vallen
);
120 for (i
= 0; i
< vallen
; i
++) {
122 *(ptr
++) = xd
[b
>> 4];
123 *(ptr
++) = xd
[b
& 0xf];
127 static void evmgr_put(struct zbuf
*zb
, const char *fmt
, ...)
129 const char *pos
, *nxt
, *str
;
131 const union sockunion
*su
;
136 for (pos
= fmt
; (nxt
= strchr(pos
, '%')) != NULL
; pos
= nxt
+ 2) {
137 zbuf_put(zb
, pos
, nxt
-pos
);
143 zb
->tail
+= snprintf((char *) zb
->tail
, zbuf_tailroom(zb
), "%u", va_arg(va
, uint32_t));
146 str
= va_arg(va
, const char *);
147 zbuf_put(zb
, str
, strlen(str
));
150 su
= va_arg(va
, const union sockunion
*);
151 if (sockunion2str(su
, (char *) zb
->tail
, zbuf_tailroom(zb
)))
152 zb
->tail
+= strlen((char *) zb
->tail
);
157 bin
= va_arg(va
, const uint8_t *);
158 len
= va_arg(va
, int);
159 evmgr_hexdump(zb
, bin
, len
);
164 zbuf_put(zb
, pos
, strlen(pos
));
167 static void evmgr_submit(struct event_manager
*evmgr
, struct zbuf
*obuf
)
173 zbuf_put(obuf
, "\n", 1);
174 zbufq_queue(&evmgr
->obuf
, obuf
);
176 thread_add_write(master
, evmgr_write
, evmgr
, evmgr
->fd
,
180 static int evmgr_reconnect(struct thread
*t
)
182 struct event_manager
*evmgr
= THREAD_ARG(t
);
185 evmgr
->t_reconnect
= NULL
;
186 if (evmgr
->fd
>= 0 || !nhrp_event_socket_path
) return 0;
188 fd
= sock_open_unix(nhrp_event_socket_path
);
190 zlog_warn("%s: failure connecting nhrp-event socket: %s",
191 __PRETTY_FUNCTION__
, strerror(errno
));
192 zbufq_reset(&evmgr
->obuf
);
193 thread_add_timer(master
, evmgr_reconnect
, evmgr
, 10,
194 &evmgr
->t_reconnect
);
198 zlog_info("Connected to Event Manager");
200 thread_add_read(master
, evmgr_read
, evmgr
, evmgr
->fd
, &evmgr
->t_read
);
205 static struct event_manager evmgr_connection
;
207 void evmgr_init(void)
209 struct event_manager
*evmgr
= &evmgr_connection
;
212 zbuf_init(&evmgr
->ibuf
, evmgr
->ibuf_data
, sizeof(evmgr
->ibuf_data
), 0);
213 zbufq_init(&evmgr
->obuf
);
214 thread_add_timer_msec(master
, evmgr_reconnect
, evmgr
, 10,
215 &evmgr
->t_reconnect
);
218 void evmgr_set_socket(const char *socket
)
220 if (nhrp_event_socket_path
) {
221 free((char *) nhrp_event_socket_path
);
222 nhrp_event_socket_path
= NULL
;
225 nhrp_event_socket_path
= strdup(socket
);
226 evmgr_connection_error(&evmgr_connection
);
229 void evmgr_terminate(void)
233 void evmgr_notify(const char *name
, struct nhrp_cache
*c
, void (*cb
)(struct nhrp_reqid
*, void *))
235 struct event_manager
*evmgr
= &evmgr_connection
;
237 struct nhrp_interface
*nifp
= c
->ifp
->info
;
239 afi_t afi
= family2afi(sockunion_family(&c
->remote_addr
));
241 if (!nhrp_event_socket_path
) {
242 cb(&c
->eventid
, (void*) "accept");
246 debugf(NHRP_DEBUG_EVENT
, "evmgr: sending event %s", name
);
248 vc
= c
->new.peer
? c
->new.peer
->vc
: NULL
;
249 zb
= zbuf_alloc(1024 + (vc
? (vc
->local
.certlen
+ vc
->remote
.certlen
) * 2 : 0));
252 nhrp_reqid_free(&nhrp_event_reqid
, &c
->eventid
);
255 nhrp_reqid_alloc(&nhrp_event_reqid
, &c
->eventid
, cb
));
266 nhrp_cache_type_str
[c
->new.type
],
267 nhrp_cache_type_str
[c
->cur
.type
],
268 (unsigned int) nhrp_cache_counts
[NHRP_CACHE_NHS
],
270 &nifp
->afi
[afi
].addr
);
280 c
->new.peer
->requested
? "yes" : "no",
282 vc
->local
.cert
, vc
->local
.certlen
,
283 &c
->remote_addr
, &vc
->remote
.nbma
,
284 vc
->remote
.cert
, vc
->remote
.certlen
);
287 evmgr_submit(evmgr
, zb
);