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/>.
20 * @file transport/transport_api2_monitor.c
21 * @brief implementation of the gnunet_transport_monitor_service.h API
22 * @author Christian Grothoff
25 #include "gnunet_util_lib.h"
26 #include "gnunet_protocols.h"
27 #include "gnunet_transport_monitor_service.h"
28 #include "transport.h"
32 * Opaque handle to the transport service for monitors.
34 struct GNUNET_TRANSPORT_MonitorContext
39 const struct GNUNET_CONFIGURATION_Handle *cfg;
42 * Queue to talk to the transport service.
44 struct GNUNET_MQ_Handle *mq;
47 * Peer we monitor, all zeros for "all"
49 struct GNUNET_PeerIdentity peer;
52 * #GNUNET_YES to return the current state and then end.
57 * Function to call with monitor data.
59 GNUNET_TRANSPORT_MonitorCallback cb;
70 * (re)connect our monitor to the transport service
72 * @param mc handle to reconnect
75 reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc);
79 * Send message to the transport service about our montoring
82 * @param ai address to delete
85 send_start_monitor (struct GNUNET_TRANSPORT_MonitorContext *mc)
87 struct GNUNET_MQ_Envelope *env;
88 struct GNUNET_TRANSPORT_MonitorStart *smm;
92 env = GNUNET_MQ_msg (smm,
93 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START);
94 smm->one_shot = htonl ((uint32_t) mc->one_shot);
96 GNUNET_MQ_send (mc->mq,
102 * Disconnect from the transport service.
104 * @param mc service to disconnect from
107 disconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
111 GNUNET_MQ_destroy (mc->mq);
117 * Function called on MQ errors. Reconnects to the service.
119 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
120 * @param error what error happened?
123 error_handler (void *cls,
124 enum GNUNET_MQ_Error error)
126 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
128 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
129 "MQ failure %d, reconnecting to transport service.\n",
132 /* TODO: maybe do this with exponential backoff/delay */
138 * Transport service sends us information about what is going on.
139 * Check if @a md is well-formed.
141 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
142 * @param md the monitor data we got
143 * @return #GNUNET_OK if @a smt is well-formed
146 check_monitor_data (void *cls,
147 const struct GNUNET_TRANSPORT_MonitorData *md)
149 uint16_t len = ntohs (md->header.size) - sizeof (*md);
150 const char *addr = (const char *) &md[1];
154 ('\0' != addr[len-1]) )
157 return GNUNET_SYSERR;
164 * Transport service sends us information about what is going on.
166 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
167 * @param md monitor data
170 handle_monitor_data (void *cls,
171 const struct GNUNET_TRANSPORT_MonitorData *md)
173 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
174 struct GNUNET_TRANSPORT_MonitorInformation mi;
176 mi.address = (const char *) &md[1];
177 mi.nt = (enum GNUNET_NetworkType) ntohl (md->nt);
178 mi.cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (md->cs);
179 mi.num_msg_pending = ntohl (md->num_msg_pending);
180 mi.num_bytes_pending = ntohl (md->num_bytes_pending);
181 mi.last_validation = GNUNET_TIME_absolute_ntoh (md->last_validation);
182 mi.valid_until = GNUNET_TIME_absolute_ntoh (md->valid_until);
183 mi.next_validation = GNUNET_TIME_absolute_ntoh (md->next_validation);
184 mi.rtt = GNUNET_TIME_relative_ntoh (md->rtt);
192 * One shot was requested, and transport service is done.
194 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
195 * @param me end message
198 handle_monitor_end (void *cls,
199 const struct GNUNET_MessageHeader *me)
201 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
203 if (GNUNET_YES != mc->one_shot)
213 GNUNET_TRANSPORT_monitor_cancel (mc);
218 * (re)connect our monitor to the transport service
220 * @param mc handle to reconnect
223 reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
225 struct GNUNET_MQ_MessageHandler handlers[] = {
226 GNUNET_MQ_hd_var_size (monitor_data,
227 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA,
228 struct GNUNET_TRANSPORT_MonitorData,
230 GNUNET_MQ_hd_fixed_size (monitor_end,
231 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_END,
232 struct GNUNET_MessageHeader,
234 GNUNET_MQ_handler_end()
237 mc->mq = GNUNET_CLIENT_connect (mc->cfg,
244 send_start_monitor (mc);
249 * Return information about a specific peer or all peers currently known to
250 * transport service once or in monitoring mode. To obtain information about
251 * a specific peer, a peer identity can be passed. To obtain information about
252 * all peers currently known to transport service, NULL can be passed as peer
255 * For each peer, the callback is called with information about the address used
256 * to communicate with this peer, the state this peer is currently in and the
257 * the current timeout for this state.
259 * Upon completion, the #GNUNET_TRANSPORT_PeerIterateCallback is called one
260 * more time with `NULL`. After this, the operation must no longer be
261 * explicitly canceled.
263 * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the
266 * @param cfg configuration to use
267 * @param peer a specific peer identity to obtain information for,
269 * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL),
270 * #GNUNET_NO to monitor peers continuously
271 * @param cb function to call with the results
272 * @param cb_cls closure for @a mc
274 struct GNUNET_TRANSPORT_MonitorContext *
275 GNUNET_TRANSPORT_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg,
276 const struct GNUNET_PeerIdentity *peer,
278 GNUNET_TRANSPORT_MonitorCallback cb,
281 struct GNUNET_TRANSPORT_MonitorContext *mc;
283 mc = GNUNET_new (struct GNUNET_TRANSPORT_MonitorContext);
287 mc->one_shot = one_shot;
302 * Cancel request to monitor peers
304 * @param pmc handle for the request to cancel
307 GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *mc)
313 /* end of transport_api2_monitor.c */