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;
71 * (re)connect our monitor to the transport service
73 * @param mc handle to reconnect
76 reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc);
80 * Send message to the transport service about our montoring
83 * @param ai address to delete
86 send_start_monitor (struct GNUNET_TRANSPORT_MonitorContext *mc)
88 struct GNUNET_MQ_Envelope *env;
89 struct GNUNET_TRANSPORT_MonitorStart *smm;
93 env = GNUNET_MQ_msg (smm, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START);
94 smm->one_shot = htonl ((uint32_t) mc->one_shot);
96 GNUNET_MQ_send (mc->mq, env);
101 * Disconnect from the transport service.
103 * @param mc service to disconnect from
106 disconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
110 GNUNET_MQ_destroy (mc->mq);
116 * Function called on MQ errors. Reconnects to the service.
118 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
119 * @param error what error happened?
122 error_handler (void *cls, enum GNUNET_MQ_Error error)
124 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
126 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
127 "MQ failure %d, reconnecting to transport service.\n",
130 /* TODO: maybe do this with exponential backoff/delay */
136 * Transport service sends us information about what is going on.
137 * Check if @a md is well-formed.
139 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
140 * @param md the monitor data we got
141 * @return #GNUNET_OK if @a smt is well-formed
144 check_monitor_data (void *cls, const struct GNUNET_TRANSPORT_MonitorData *md)
147 GNUNET_MQ_check_zero_termination (md);
153 * Transport service sends us information about what is going on.
155 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
156 * @param md monitor data
159 handle_monitor_data (void *cls, const struct GNUNET_TRANSPORT_MonitorData *md)
161 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
162 struct GNUNET_TRANSPORT_MonitorInformation mi;
164 mi.address = (const char *) &md[1];
165 mi.nt = (enum GNUNET_NetworkType) ntohl (md->nt);
166 mi.cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (md->cs);
167 mi.num_msg_pending = ntohl (md->num_msg_pending);
168 mi.num_bytes_pending = ntohl (md->num_bytes_pending);
169 mi.last_validation = GNUNET_TIME_absolute_ntoh (md->last_validation);
170 mi.valid_until = GNUNET_TIME_absolute_ntoh (md->valid_until);
171 mi.next_validation = GNUNET_TIME_absolute_ntoh (md->next_validation);
172 mi.rtt = GNUNET_TIME_relative_ntoh (md->rtt);
173 mc->cb (mc->cb_cls, &md->peer, &mi);
178 * One shot was requested, and transport service is done.
180 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
181 * @param me end message
184 handle_monitor_end (void *cls, const struct GNUNET_MessageHeader *me)
186 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
188 if (GNUNET_YES != mc->one_shot)
195 mc->cb (mc->cb_cls, NULL, NULL);
196 GNUNET_TRANSPORT_monitor_cancel (mc);
201 * (re)connect our monitor to the transport service
203 * @param mc handle to reconnect
206 reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
208 struct GNUNET_MQ_MessageHandler handlers[] =
209 { GNUNET_MQ_hd_var_size (monitor_data,
210 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA,
211 struct GNUNET_TRANSPORT_MonitorData,
213 GNUNET_MQ_hd_fixed_size (monitor_end,
214 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_END,
215 struct GNUNET_MessageHeader,
217 GNUNET_MQ_handler_end () };
220 GNUNET_CLIENT_connect (mc->cfg, "transport", handlers, &error_handler, mc);
223 send_start_monitor (mc);
228 * Return information about a specific peer or all peers currently known to
229 * transport service once or in monitoring mode. To obtain information about
230 * a specific peer, a peer identity can be passed. To obtain information about
231 * all peers currently known to transport service, NULL can be passed as peer
234 * For each peer, the callback is called with information about the address used
235 * to communicate with this peer, the state this peer is currently in and the
236 * the current timeout for this state.
238 * Upon completion, the #GNUNET_TRANSPORT_PeerIterateCallback is called one
239 * more time with `NULL`. After this, the operation must no longer be
240 * explicitly canceled.
242 * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the
245 * @param cfg configuration to use
246 * @param peer a specific peer identity to obtain information for,
248 * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL),
249 * #GNUNET_NO to monitor peers continuously
250 * @param cb function to call with the results
251 * @param cb_cls closure for @a mc
253 struct GNUNET_TRANSPORT_MonitorContext *
254 GNUNET_TRANSPORT_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg,
255 const struct GNUNET_PeerIdentity *peer,
257 GNUNET_TRANSPORT_MonitorCallback cb,
260 struct GNUNET_TRANSPORT_MonitorContext *mc;
262 mc = GNUNET_new (struct GNUNET_TRANSPORT_MonitorContext);
266 mc->one_shot = one_shot;
280 * Cancel request to monitor peers
282 * @param pmc handle for the request to cancel
285 GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *mc)
292 /* end of transport_api2_monitor.c */