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 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_add_read(master
, evmgr_read
, evmgr
, evmgr
->fd
, &evmgr
->t_read
);
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_add_write(master
, evmgr_write
, evmgr
, evmgr
->fd
,
103 evmgr_connection_error(evmgr
);
109 static void evmgr_hexdump(struct zbuf
*zb
, const uint8_t *val
, size_t vallen
)
111 static const char xd
[] = "0123456789abcdef";
115 ptr
= zbuf_pushn(zb
, 2*vallen
);
118 for (i
= 0; i
< vallen
; i
++) {
120 *(ptr
++) = xd
[b
>> 4];
121 *(ptr
++) = xd
[b
& 0xf];
125 static void evmgr_put(struct zbuf
*zb
, const char *fmt
, ...)
127 const char *pos
, *nxt
, *str
;
129 const union sockunion
*su
;
134 for (pos
= fmt
; (nxt
= strchr(pos
, '%')) != NULL
; pos
= nxt
+ 2) {
135 zbuf_put(zb
, pos
, nxt
-pos
);
141 zb
->tail
+= snprintf((char *) zb
->tail
, zbuf_tailroom(zb
), "%u", va_arg(va
, uint32_t));
144 str
= va_arg(va
, const char *);
145 zbuf_put(zb
, str
, strlen(str
));
148 su
= va_arg(va
, const union sockunion
*);
149 if (sockunion2str(su
, (char *) zb
->tail
, zbuf_tailroom(zb
)))
150 zb
->tail
+= strlen((char *) zb
->tail
);
155 bin
= va_arg(va
, const uint8_t *);
156 len
= va_arg(va
, int);
157 evmgr_hexdump(zb
, bin
, len
);
162 zbuf_put(zb
, pos
, strlen(pos
));
165 static void evmgr_submit(struct event_manager
*evmgr
, struct zbuf
*obuf
)
171 zbuf_put(obuf
, "\n", 1);
172 zbufq_queue(&evmgr
->obuf
, obuf
);
174 thread_add_write(master
, evmgr_write
, evmgr
, evmgr
->fd
,
178 static int evmgr_reconnect(struct thread
*t
)
180 struct event_manager
*evmgr
= THREAD_ARG(t
);
183 evmgr
->t_reconnect
= NULL
;
184 if (evmgr
->fd
>= 0 || !nhrp_event_socket_path
) return 0;
186 fd
= sock_open_unix(nhrp_event_socket_path
);
188 zlog_warn("%s: failure connecting nhrp-event socket: %s",
189 __PRETTY_FUNCTION__
, strerror(errno
));
190 zbufq_reset(&evmgr
->obuf
);
191 thread_add_timer(master
, evmgr_reconnect
, evmgr
, 10,
192 &evmgr
->t_reconnect
);
196 zlog_info("Connected to Event Manager");
198 thread_add_read(master
, evmgr_read
, evmgr
, evmgr
->fd
, &evmgr
->t_read
);
203 static struct event_manager evmgr_connection
;
205 void evmgr_init(void)
207 struct event_manager
*evmgr
= &evmgr_connection
;
210 zbuf_init(&evmgr
->ibuf
, evmgr
->ibuf_data
, sizeof(evmgr
->ibuf_data
), 0);
211 zbufq_init(&evmgr
->obuf
);
212 thread_add_timer_msec(master
, evmgr_reconnect
, evmgr
, 10,
213 &evmgr
->t_reconnect
);
216 void evmgr_set_socket(const char *socket
)
218 if (nhrp_event_socket_path
) {
219 free((char *) nhrp_event_socket_path
);
220 nhrp_event_socket_path
= NULL
;
223 nhrp_event_socket_path
= strdup(socket
);
224 evmgr_connection_error(&evmgr_connection
);
227 void evmgr_terminate(void)
231 void evmgr_notify(const char *name
, struct nhrp_cache
*c
, void (*cb
)(struct nhrp_reqid
*, void *))
233 struct event_manager
*evmgr
= &evmgr_connection
;
235 struct nhrp_interface
*nifp
= c
->ifp
->info
;
237 afi_t afi
= family2afi(sockunion_family(&c
->remote_addr
));
239 if (!nhrp_event_socket_path
) {
240 cb(&c
->eventid
, (void*) "accept");
244 debugf(NHRP_DEBUG_EVENT
, "evmgr: sending event %s", name
);
246 vc
= c
->new.peer
? c
->new.peer
->vc
: NULL
;
247 zb
= zbuf_alloc(1024 + (vc
? (vc
->local
.certlen
+ vc
->remote
.certlen
) * 2 : 0));
250 nhrp_reqid_free(&nhrp_event_reqid
, &c
->eventid
);
253 nhrp_reqid_alloc(&nhrp_event_reqid
, &c
->eventid
, cb
));
264 nhrp_cache_type_str
[c
->new.type
],
265 nhrp_cache_type_str
[c
->cur
.type
],
266 (unsigned int) nhrp_cache_counts
[NHRP_CACHE_NHS
],
268 &nifp
->afi
[afi
].addr
);
278 c
->new.peer
->requested
? "yes" : "no",
280 vc
->local
.cert
, vc
->local
.certlen
,
281 &c
->remote_addr
, &vc
->remote
.nbma
,
282 vc
->remote
.cert
, vc
->remote
.certlen
);
285 evmgr_submit(evmgr
, zb
);