2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file src/transport/gnunet-transport.c
23 * @brief Tool to help configure, measure and control the transport subsystem.
24 * @author Christian Grothoff
26 * This utility can be used to test if a transport mechanism for
27 * GNUnet is properly configured.
31 #include "gnunet_program_lib.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_transport_service.h"
37 static struct GNUNET_TRANSPORT_Handle *handle;
39 static int benchmark_send;
41 static int benchmark_receive;
45 static unsigned long long traffic_received;
47 static unsigned long long traffic_sent;
49 static struct GNUNET_TIME_Absolute start_time;
51 static struct GNUNET_TRANSPORT_TransmitHandle *th;
53 static struct GNUNET_PeerIdentity pid;
55 static GNUNET_SCHEDULER_TaskIdentifier end;
59 * Shutdown, print statistics.
62 do_disconnect (void *cls,
63 const struct GNUNET_SCHEDULER_TaskContext *tc)
65 struct GNUNET_TIME_Relative duration;
69 GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
72 GNUNET_TRANSPORT_disconnect (handle);
73 if (benchmark_receive)
75 duration = GNUNET_TIME_absolute_get_duration (start_time);
77 "Received %llu bytes/s (%llu bytes in %llu ms)\n",
78 1000 * traffic_received / (1+duration.rel_value),
80 (unsigned long long) duration.rel_value);
84 duration = GNUNET_TIME_absolute_get_duration (start_time);
86 "Transmitted %llu bytes/s (%llu bytes in %llu ms)\n",
87 1000 * traffic_sent / (1+duration.rel_value),
89 (unsigned long long) duration.rel_value);
95 * Function called to notify a client about the socket
96 * begin ready to queue more data. "buf" will be
97 * NULL and "size" zero if the socket was closed for
98 * writing in the meantime.
101 * @param size number of bytes available in buf
102 * @param buf where the callee should write the message
103 * @return number of bytes written to buf
106 transmit_data (void *cls, size_t size,
109 struct GNUNET_MessageHeader *m = buf;
111 GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
112 GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
113 m->size = ntohs (size);
114 m->type = ntohs (GNUNET_MESSAGE_TYPE_DUMMY);
115 memset (&m[1], 52, size - sizeof (struct GNUNET_MessageHeader));
116 traffic_sent += size;
117 th = GNUNET_TRANSPORT_notify_transmit_ready (handle,
121 GNUNET_TIME_UNIT_FOREVER_REL,
122 &transmit_data, NULL);
124 "Transmitting %u bytes to %s\n",
132 * Function called to notify transport users that another
133 * peer connected to us.
136 * @param peer the peer that connected
137 * @param ats performance data
138 * @param ats_count number of entries in ats (excluding 0-termination)
141 notify_connect (void *cls,
142 const struct GNUNET_PeerIdentity
145 GNUNET_ATS_Information
146 * ats, uint32_t ats_count)
151 if (0 != memcmp (&pid,
153 sizeof (struct GNUNET_PeerIdentity)))
158 start_time = GNUNET_TIME_absolute_get ();
159 th = GNUNET_TRANSPORT_notify_transmit_ready (handle,
163 GNUNET_TIME_UNIT_FOREVER_REL,
164 &transmit_data, NULL);
168 /* all done, terminate instantly */
169 GNUNET_SCHEDULER_cancel (end);
170 end = GNUNET_SCHEDULER_add_now (&do_disconnect,
177 * Function called to notify transport users that another
178 * peer disconnected from us.
181 * @param peer the peer that disconnected
184 notify_disconnect (void *cls,
186 GNUNET_PeerIdentity * peer)
189 "Disconnected from %s\n",
191 if ( (0 == memcmp (&pid,
193 sizeof (struct GNUNET_PeerIdentity))) &&
196 GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
198 GNUNET_SCHEDULER_cancel (end);
199 end = GNUNET_SCHEDULER_add_now (&do_disconnect,
206 * Function called by the transport for each received message.
209 * @param peer (claimed) identity of the other peer
210 * @param message the message
211 * @param ats performance data
212 * @param ats_count number of entries in ats
215 notify_receive (void *cls,
217 GNUNET_PeerIdentity * peer,
219 GNUNET_MessageHeader *
222 GNUNET_ATS_Information
223 * ats, uint32_t ats_count)
225 if (! benchmark_receive)
228 "Received %u bytes from %s\n",
229 (unsigned int) ntohs (message->size),
231 if (traffic_received == 0)
232 start_time = GNUNET_TIME_absolute_get ();
233 traffic_received += ntohs (message->size);
238 * Main function that will be run by the scheduler.
241 * @param args remaining command-line arguments
242 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
243 * @param cfg configuration
246 run (void *cls, char *const *args, const char *cfgfile,
247 const struct GNUNET_CONFIGURATION_Handle *cfg)
249 if (benchmark_send && (NULL == cpid))
251 fprintf (stderr, _("Option `%s' makes no sense without option `%s'.\n"),
259 GNUNET_CRYPTO_hash_from_string (cpid, &pid.hashPubKey))
262 _("Failed to parse peer identity `%s'\n"),
266 handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL,
270 GNUNET_TRANSPORT_try_connect (handle, &pid);
271 end = GNUNET_SCHEDULER_add_delayed (benchmark_send
272 ? GNUNET_TIME_UNIT_FOREVER_REL
273 : GNUNET_TIME_UNIT_SECONDS,
276 } else if (benchmark_receive)
278 handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL,
282 GNUNET_TRANSPORT_try_connect (handle, &pid);
283 end = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
291 main (int argc, char *const *argv)
293 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
294 {'b', "benchmark", NULL,
295 gettext_noop ("measure how fast we are receiving data (until CTRL-C)"),
296 0, &GNUNET_GETOPT_set_one, &benchmark_receive},
297 {'C', "connect", "PEER",
298 gettext_noop ("try to connect to the given peer"),
299 1, &GNUNET_GETOPT_set_string, &cpid},
301 gettext_noop ("send data for benchmarking to the other peer (until CTRL-C)"),
302 0, &GNUNET_GETOPT_set_one, &benchmark_send},
303 GNUNET_GETOPT_OPTION_END
306 GNUNET_PROGRAM_run (argc, argv, "gnunet-transport",
307 gettext_noop ("Direct access to transport service."),
308 options, &run, NULL)) ? ret : 1;
312 /* end of gnunet-transport.c */