2 This file is part of GNUnet.
3 Copyright (C) 2018 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file transport/transport_api2_monitor.c
23 * @brief implementation of the gnunet_transport_monitor_service.h API
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_transport_monitor_service.h"
30 #include "transport.h"
34 * Opaque handle to the transport service for monitors.
36 struct GNUNET_TRANSPORT_MonitorContext
41 const struct GNUNET_CONFIGURATION_Handle *cfg;
44 * Queue to talk to the transport service.
46 struct GNUNET_MQ_Handle *mq;
49 * Peer we monitor, all zeros for "all"
51 struct GNUNET_PeerIdentity peer;
54 * #GNUNET_YES to return the current state and then end.
59 * Function to call with monitor data.
61 GNUNET_TRANSPORT_MonitorCallback cb;
72 * (re)connect our monitor to the transport service
74 * @param mc handle to reconnect
77 reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc);
81 * Send message to the transport service about our montoring
84 * @param ai address to delete
87 send_start_monitor (struct GNUNET_TRANSPORT_MonitorContext *mc)
89 struct GNUNET_MQ_Envelope *env;
90 struct GNUNET_TRANSPORT_MonitorStart *smm;
94 env = GNUNET_MQ_msg (smm,
95 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START);
96 smm->one_shot = htonl ((uint32_t) mc->one_shot);
98 GNUNET_MQ_send (mc->mq,
104 * Disconnect from the transport service.
106 * @param mc service to disconnect from
109 disconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
113 GNUNET_MQ_destroy (mc->mq);
119 * Function called on MQ errors. Reconnects to the service.
121 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
122 * @param error what error happened?
125 error_handler (void *cls,
126 enum GNUNET_MQ_Error error)
128 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
130 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
131 "MQ failure %d, reconnecting to transport service.\n",
134 /* TODO: maybe do this with exponential backoff/delay */
140 * Transport service sends us information about what is going on.
141 * Check if @a md is well-formed.
143 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
144 * @param md the monitor data we got
145 * @return #GNUNET_OK if @a smt is well-formed
148 check_monitor_data (void *cls,
149 const struct GNUNET_TRANSPORT_MonitorData *md)
151 uint16_t len = ntohs (md->header.size) - sizeof (*md);
152 const char *addr = (const char *) &md[1];
156 ('\0' != addr[len-1]) )
159 return GNUNET_SYSERR;
166 * Transport service sends us information about what is going on.
168 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
169 * @param md monitor data
172 handle_monitor_data (void *cls,
173 const struct GNUNET_TRANSPORT_MonitorData *md)
175 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
176 struct GNUNET_TRANSPORT_MonitorInformation mi;
178 mi.address = (const char *) &md[1];
179 mi.nt = (enum GNUNET_NetworkType) ntohl (md->nt);
180 mi.cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (md->cs);
181 mi.num_msg_pending = ntohl (md->num_msg_pending);
182 mi.num_bytes_pending = ntohl (md->num_bytes_pending);
183 mi.last_validation = GNUNET_TIME_absolute_ntoh (md->last_validation);
184 mi.valid_until = GNUNET_TIME_absolute_ntoh (md->valid_until);
185 mi.next_validation = GNUNET_TIME_absolute_ntoh (md->next_validation);
186 mi.rtt = GNUNET_TIME_relative_ntoh (md->rtt);
194 * One shot was requested, and transport service is done.
196 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
197 * @param me end message
200 handle_monitor_end (void *cls,
201 const struct GNUNET_MessageHeader *me)
203 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
205 if (GNUNET_YES != mc->one_shot)
215 GNUNET_TRANSPORT_monitor_cancel (mc);
220 * (re)connect our monitor to the transport service
222 * @param mc handle to reconnect
225 reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
227 struct GNUNET_MQ_MessageHandler handlers[] = {
228 GNUNET_MQ_hd_var_size (monitor_data,
229 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA,
230 struct GNUNET_TRANSPORT_MonitorData,
232 GNUNET_MQ_hd_fixed_size (monitor_end,
233 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_END,
234 struct GNUNET_MessageHeader,
236 GNUNET_MQ_handler_end()
239 mc->mq = GNUNET_CLIENT_connect (mc->cfg,
246 send_start_monitor (mc);
251 * Return information about a specific peer or all peers currently known to
252 * transport service once or in monitoring mode. To obtain information about
253 * a specific peer, a peer identity can be passed. To obtain information about
254 * all peers currently known to transport service, NULL can be passed as peer
257 * For each peer, the callback is called with information about the address used
258 * to communicate with this peer, the state this peer is currently in and the
259 * the current timeout for this state.
261 * Upon completion, the #GNUNET_TRANSPORT_PeerIterateCallback is called one
262 * more time with `NULL`. After this, the operation must no longer be
263 * explicitly canceled.
265 * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the
268 * @param cfg configuration to use
269 * @param peer a specific peer identity to obtain information for,
271 * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL),
272 * #GNUNET_NO to monitor peers continuously
273 * @param cb function to call with the results
274 * @param cb_cls closure for @a mc
276 struct GNUNET_TRANSPORT_MonitorContext *
277 GNUNET_TRANSPORT_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg,
278 const struct GNUNET_PeerIdentity *peer,
280 GNUNET_TRANSPORT_MonitorCallback cb,
283 struct GNUNET_TRANSPORT_MonitorContext *mc;
285 mc = GNUNET_new (struct GNUNET_TRANSPORT_MonitorContext);
289 mc->one_shot = one_shot;
304 * Cancel request to monitor peers
306 * @param pmc handle for the request to cancel
309 GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *mc)
315 /* end of transport_api2_monitor.c */