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=%" SCNu32
, &eventid
) != 1)
64 if (sscanf(buf
, "result=%63s", result
) != 1)
67 debugf(NHRP_DEBUG_EVENT
, "evmgr: received: eventid=%d result=%s",
69 if (eventid
&& result
[0]) {
70 struct nhrp_reqid
*r
=
71 nhrp_reqid_lookup(&nhrp_event_reqid
, eventid
);
77 static int evmgr_read(struct thread
*t
)
79 struct event_manager
*evmgr
= THREAD_ARG(t
);
80 struct zbuf
*ibuf
= &evmgr
->ibuf
;
84 if (zbuf_read(ibuf
, evmgr
->fd
, (size_t)-1) < 0) {
85 evmgr_connection_error(evmgr
);
89 /* Process all messages in buffer */
90 while (zbuf_may_pull_until(ibuf
, "\n\n", &msg
))
91 evmgr_recv_message(evmgr
, &msg
);
93 thread_add_read(master
, evmgr_read
, evmgr
, evmgr
->fd
, &evmgr
->t_read
);
97 static int evmgr_write(struct thread
*t
)
99 struct event_manager
*evmgr
= THREAD_ARG(t
);
102 evmgr
->t_write
= NULL
;
103 r
= zbufq_write(&evmgr
->obuf
, evmgr
->fd
);
105 thread_add_write(master
, evmgr_write
, evmgr
, evmgr
->fd
,
108 evmgr_connection_error(evmgr
);
114 static void evmgr_hexdump(struct zbuf
*zb
, const uint8_t *val
, size_t vallen
)
116 static const char xd
[] = "0123456789abcdef";
120 ptr
= zbuf_pushn(zb
, 2 * vallen
);
124 for (i
= 0; i
< vallen
; i
++) {
126 *(ptr
++) = xd
[b
>> 4];
127 *(ptr
++) = xd
[b
& 0xf];
131 static void evmgr_put(struct zbuf
*zb
, const char *fmt
, ...)
133 const char *pos
, *nxt
, *str
;
135 const union sockunion
*su
;
140 for (pos
= fmt
; (nxt
= strchr(pos
, '%')) != NULL
; pos
= nxt
+ 2) {
141 zbuf_put(zb
, pos
, nxt
- pos
);
148 snprintf((char *)zb
->tail
, zbuf_tailroom(zb
),
149 "%u", va_arg(va
, uint32_t));
152 str
= va_arg(va
, const char *);
153 zbuf_put(zb
, str
, strlen(str
));
156 su
= va_arg(va
, const union sockunion
*);
157 if (sockunion2str(su
, (char *)zb
->tail
,
159 zb
->tail
+= strlen((char *)zb
->tail
);
164 bin
= va_arg(va
, const uint8_t *);
165 len
= va_arg(va
, int);
166 evmgr_hexdump(zb
, bin
, len
);
171 zbuf_put(zb
, pos
, strlen(pos
));
174 static void evmgr_submit(struct event_manager
*evmgr
, struct zbuf
*obuf
)
180 zbuf_put(obuf
, "\n", 1);
181 zbufq_queue(&evmgr
->obuf
, obuf
);
183 thread_add_write(master
, evmgr_write
, evmgr
, evmgr
->fd
,
187 static int evmgr_reconnect(struct thread
*t
)
189 struct event_manager
*evmgr
= THREAD_ARG(t
);
192 evmgr
->t_reconnect
= NULL
;
193 if (evmgr
->fd
>= 0 || !nhrp_event_socket_path
)
196 fd
= sock_open_unix(nhrp_event_socket_path
);
198 zlog_warn("%s: failure connecting nhrp-event socket: %s",
199 __PRETTY_FUNCTION__
, strerror(errno
));
200 zbufq_reset(&evmgr
->obuf
);
201 thread_add_timer(master
, evmgr_reconnect
, evmgr
, 10,
202 &evmgr
->t_reconnect
);
206 zlog_info("Connected to Event Manager");
208 thread_add_read(master
, evmgr_read
, evmgr
, evmgr
->fd
, &evmgr
->t_read
);
213 static struct event_manager evmgr_connection
;
215 void evmgr_init(void)
217 struct event_manager
*evmgr
= &evmgr_connection
;
220 zbuf_init(&evmgr
->ibuf
, evmgr
->ibuf_data
, sizeof(evmgr
->ibuf_data
), 0);
221 zbufq_init(&evmgr
->obuf
);
222 thread_add_timer_msec(master
, evmgr_reconnect
, evmgr
, 10,
223 &evmgr
->t_reconnect
);
226 void evmgr_set_socket(const char *socket
)
228 if (nhrp_event_socket_path
) {
229 free((char *)nhrp_event_socket_path
);
230 nhrp_event_socket_path
= NULL
;
233 nhrp_event_socket_path
= strdup(socket
);
234 evmgr_connection_error(&evmgr_connection
);
237 void evmgr_terminate(void)
241 void evmgr_notify(const char *name
, struct nhrp_cache
*c
,
242 void (*cb
)(struct nhrp_reqid
*, void *))
244 struct event_manager
*evmgr
= &evmgr_connection
;
246 struct nhrp_interface
*nifp
= c
->ifp
->info
;
248 afi_t afi
= family2afi(sockunion_family(&c
->remote_addr
));
250 if (!nhrp_event_socket_path
) {
251 cb(&c
->eventid
, (void *)"accept");
255 debugf(NHRP_DEBUG_EVENT
, "evmgr: sending event %s", name
);
257 vc
= c
->new.peer
? c
->new.peer
->vc
: NULL
;
259 1024 + (vc
? (vc
->local
.certlen
+ vc
->remote
.certlen
) * 2 : 0));
262 nhrp_reqid_free(&nhrp_event_reqid
, &c
->eventid
);
263 evmgr_put(zb
, "eventid=%u\n",
264 nhrp_reqid_alloc(&nhrp_event_reqid
, &c
->eventid
, cb
));
274 name
, nhrp_cache_type_str
[c
->new.type
],
275 nhrp_cache_type_str
[c
->cur
.type
],
276 (unsigned int)nhrp_cache_counts
[NHRP_CACHE_NHS
], c
->ifp
->name
,
277 &nifp
->afi
[afi
].addr
);
287 c
->new.peer
->requested
? "yes" : "no",
288 &vc
->local
.nbma
, vc
->local
.cert
, vc
->local
.certlen
,
289 &c
->remote_addr
, &vc
->remote
.nbma
, vc
->remote
.cert
,
293 evmgr_submit(evmgr
, zb
);