diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/transport/Makefile.am | 12 | ||||
-rw-r--r-- | src/transport/gnunet-service-transport_neighbours.c | 5 | ||||
-rw-r--r-- | src/transport/gnunet-service-transport_validation.c | 34 | ||||
-rw-r--r-- | src/transport/gnunet-transport-profiler.c | 1921 |
4 files changed, 1955 insertions, 17 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 8367fb1b1..46d7ef3e0 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am | |||
@@ -111,6 +111,7 @@ endif | |||
111 | endif | 111 | endif |
112 | 112 | ||
113 | noinst_PROGRAMS = \ | 113 | noinst_PROGRAMS = \ |
114 | gnunet-transport-profiler \ | ||
114 | $(WLAN_BIN_SENDER) \ | 115 | $(WLAN_BIN_SENDER) \ |
115 | $(WLAN_BIN_RECEIVER) | 116 | $(WLAN_BIN_RECEIVER) |
116 | 117 | ||
@@ -195,6 +196,17 @@ else | |||
195 | gnunet_helper_transport_bluetooth_LDFLAGS = -lbluetooth | 196 | gnunet_helper_transport_bluetooth_LDFLAGS = -lbluetooth |
196 | endif | 197 | endif |
197 | 198 | ||
199 | gnunet_transport_profiler_SOURCES = \ | ||
200 | gnunet-transport-profiler.c | ||
201 | gnunet_transport_profiler_LDADD = \ | ||
202 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
203 | $(top_builddir)/src/nat/libgnunetnat.la \ | ||
204 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
205 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
206 | $(GN_LIBINTL) | ||
207 | gnunet_transport_profiler_DEPENDENCIES = \ | ||
208 | libgnunettransport.la | ||
209 | |||
198 | gnunet_transport_SOURCES = \ | 210 | gnunet_transport_SOURCES = \ |
199 | gnunet-transport.c | 211 | gnunet-transport.c |
200 | gnunet_transport_LDADD = \ | 212 | gnunet_transport_LDADD = \ |
diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c index b11add24c..6867251f3 100644 --- a/src/transport/gnunet-service-transport_neighbours.c +++ b/src/transport/gnunet-service-transport_neighbours.c | |||
@@ -3569,6 +3569,11 @@ void delayed_disconnect (void *cls, | |||
3569 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 3569 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
3570 | "Disconnecting by request from peer %s\n", | 3570 | "Disconnecting by request from peer %s\n", |
3571 | GNUNET_i2s (&n->id)); | 3571 | GNUNET_i2s (&n->id)); |
3572 | |||
3573 | if (NULL != n->primary_address.address) | ||
3574 | GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, | ||
3575 | n->primary_address.session); | ||
3576 | |||
3572 | free_neighbour (n, GNUNET_NO); | 3577 | free_neighbour (n, GNUNET_NO); |
3573 | } | 3578 | } |
3574 | 3579 | ||
diff --git a/src/transport/gnunet-service-transport_validation.c b/src/transport/gnunet-service-transport_validation.c index ebfe963cb..3c7edd140 100644 --- a/src/transport/gnunet-service-transport_validation.c +++ b/src/transport/gnunet-service-transport_validation.c | |||
@@ -990,8 +990,8 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, | |||
990 | const char *addrend; | 990 | const char *addrend; |
991 | char *plugin_name; | 991 | char *plugin_name; |
992 | char *pos; | 992 | char *pos; |
993 | size_t alen; | 993 | size_t len_address; |
994 | size_t slen; | 994 | size_t len_plugin; |
995 | ssize_t ret; | 995 | ssize_t ret; |
996 | int buggy = GNUNET_NO; | 996 | int buggy = GNUNET_NO; |
997 | struct GNUNET_HELLO_Address address; | 997 | struct GNUNET_HELLO_Address address; |
@@ -1016,27 +1016,27 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, | |||
1016 | gettext_noop ("# PING messages received"), 1, | 1016 | gettext_noop ("# PING messages received"), 1, |
1017 | GNUNET_NO); | 1017 | GNUNET_NO); |
1018 | addr = (const char *) &ping[1]; | 1018 | addr = (const char *) &ping[1]; |
1019 | alen = ntohs (hdr->size) - sizeof (struct TransportPingMessage); | 1019 | len_address = ntohs (hdr->size) - sizeof (struct TransportPingMessage); |
1020 | /* peer wants to confirm that this is one of our addresses, this is what is | 1020 | /* peer wants to confirm that this is one of our addresses, this is what is |
1021 | * used for address validation */ | 1021 | * used for address validation */ |
1022 | 1022 | ||
1023 | sig_cache = NULL; | 1023 | sig_cache = NULL; |
1024 | sig_cache_exp = NULL; | 1024 | sig_cache_exp = NULL; |
1025 | papi = NULL; | 1025 | papi = NULL; |
1026 | if (alen > 0) | 1026 | if (len_address > 0) |
1027 | { | 1027 | { |
1028 | addrend = memchr (addr, '\0', alen); | 1028 | addrend = memchr (addr, '\0', len_address); |
1029 | if (NULL == addrend) | 1029 | if (NULL == addrend) |
1030 | { | 1030 | { |
1031 | GNUNET_break_op (0); | 1031 | GNUNET_break_op (0); |
1032 | return GNUNET_SYSERR; | 1032 | return GNUNET_SYSERR; |
1033 | } | 1033 | } |
1034 | addrend++; | 1034 | addrend++; |
1035 | slen = strlen (addr) + 1; | 1035 | len_plugin = strlen (addr) + 1; |
1036 | alen -= slen; | 1036 | len_address -= len_plugin; |
1037 | address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE; | 1037 | address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE; |
1038 | address.address = addrend; | 1038 | address.address = addrend; |
1039 | address.address_length = alen; | 1039 | address.address_length = len_address; |
1040 | address.transport_name = addr; | 1040 | address.transport_name = addr; |
1041 | address.peer = GST_my_identity; | 1041 | address.peer = GST_my_identity; |
1042 | 1042 | ||
@@ -1065,7 +1065,7 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, | |||
1065 | return GNUNET_SYSERR; | 1065 | return GNUNET_SYSERR; |
1066 | } | 1066 | } |
1067 | GNUNET_free (plugin_name); | 1067 | GNUNET_free (plugin_name); |
1068 | if (GNUNET_OK != papi->check_address (papi->cls, addrend, alen)) | 1068 | if (GNUNET_OK != papi->check_address (papi->cls, addrend, len_address)) |
1069 | { | 1069 | { |
1070 | GNUNET_STATISTICS_update (GST_stats, | 1070 | GNUNET_STATISTICS_update (GST_stats, |
1071 | gettext_noop | 1071 | gettext_noop |
@@ -1108,7 +1108,7 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, | |||
1108 | else | 1108 | else |
1109 | { | 1109 | { |
1110 | addrend = NULL; /* make gcc happy */ | 1110 | addrend = NULL; /* make gcc happy */ |
1111 | slen = 0; | 1111 | len_plugin = 0; |
1112 | static struct GNUNET_CRYPTO_EddsaSignature no_address_signature; | 1112 | static struct GNUNET_CRYPTO_EddsaSignature no_address_signature; |
1113 | static struct GNUNET_TIME_Absolute no_address_signature_expiration; | 1113 | static struct GNUNET_TIME_Absolute no_address_signature_expiration; |
1114 | 1114 | ||
@@ -1124,22 +1124,22 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, | |||
1124 | /* message with structure: | 1124 | /* message with structure: |
1125 | * [TransportPongMessage][Transport name][Address] */ | 1125 | * [TransportPongMessage][Transport name][Address] */ |
1126 | 1126 | ||
1127 | pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + alen + slen); | 1127 | pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + len_address + len_plugin); |
1128 | pong->header.size = | 1128 | pong->header.size = |
1129 | htons (sizeof (struct TransportPongMessage) + alen + slen); | 1129 | htons (sizeof (struct TransportPongMessage) + len_address + len_plugin); |
1130 | pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG); | 1130 | pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG); |
1131 | pong->purpose.size = | 1131 | pong->purpose.size = |
1132 | htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | 1132 | htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + |
1133 | sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + | 1133 | sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + |
1134 | alen + slen); | 1134 | len_address + len_plugin); |
1135 | pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN); | 1135 | pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN); |
1136 | memcpy (&pong->challenge, &ping->challenge, sizeof (ping->challenge)); | 1136 | memcpy (&pong->challenge, &ping->challenge, sizeof (ping->challenge)); |
1137 | pong->addrlen = htonl (alen + slen); | 1137 | pong->addrlen = htonl (len_address + len_plugin); |
1138 | memcpy (&pong[1], addr, slen); /* Copy transport plugin */ | 1138 | memcpy (&pong[1], addr, len_plugin); /* Copy transport plugin */ |
1139 | if (alen > 0) | 1139 | if (len_address > 0) |
1140 | { | 1140 | { |
1141 | GNUNET_assert (NULL != addrend); | 1141 | GNUNET_assert (NULL != addrend); |
1142 | memcpy (&((char *) &pong[1])[slen], addrend, alen); | 1142 | memcpy (&((char *) &pong[1])[len_plugin], addrend, len_address); |
1143 | } | 1143 | } |
1144 | if (GNUNET_TIME_absolute_get_remaining (*sig_cache_exp).rel_value_us < | 1144 | if (GNUNET_TIME_absolute_get_remaining (*sig_cache_exp).rel_value_us < |
1145 | PONG_SIGNATURE_LIFETIME.rel_value_us / 4) | 1145 | PONG_SIGNATURE_LIFETIME.rel_value_us / 4) |
diff --git a/src/transport/gnunet-transport-profiler.c b/src/transport/gnunet-transport-profiler.c new file mode 100644 index 000000000..354060ac8 --- /dev/null +++ b/src/transport/gnunet-transport-profiler.c | |||
@@ -0,0 +1,1921 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2011-2014 Christian Grothoff (and other contributing authors) | ||
4 | |||
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. | ||
9 | |||
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. | ||
14 | |||
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. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/transport/gnunet-transport.c | ||
23 | * @brief Tool to help configure, measure and control the transport subsystem. | ||
24 | * @author Christian Grothoff | ||
25 | * @author Nathan Evans | ||
26 | * | ||
27 | * This utility can be used to test if a transport mechanism for | ||
28 | * GNUnet is properly configured. | ||
29 | */ | ||
30 | #include "platform.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | #include "gnunet_resolver_service.h" | ||
33 | #include "gnunet_protocols.h" | ||
34 | #include "gnunet_transport_service.h" | ||
35 | #include "gnunet_nat_lib.h" | ||
36 | |||
37 | /** | ||
38 | * How long do we wait for the NAT test to report success? | ||
39 | * Should match NAT_SERVER_TIMEOUT in 'nat_test.c'. | ||
40 | */ | ||
41 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) | ||
42 | |||
43 | /** | ||
44 | * Timeout for a name resolution | ||
45 | */ | ||
46 | #define RESOLUTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
47 | |||
48 | /** | ||
49 | * Timeout for an operations | ||
50 | */ | ||
51 | #define OP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
52 | |||
53 | |||
54 | /** | ||
55 | * Context to store name resolutions for valiation | ||
56 | */ | ||
57 | struct ValidationResolutionContext | ||
58 | { | ||
59 | /** | ||
60 | * Next in DLL | ||
61 | */ | ||
62 | struct ValidationResolutionContext *next; | ||
63 | |||
64 | /** | ||
65 | * Previous in DLL | ||
66 | */ | ||
67 | struct ValidationResolutionContext *prev; | ||
68 | |||
69 | /** | ||
70 | * Peer identity | ||
71 | */ | ||
72 | struct GNUNET_PeerIdentity id; | ||
73 | |||
74 | /** | ||
75 | * Address to resolve | ||
76 | */ | ||
77 | struct GNUNET_HELLO_Address *addrcp; | ||
78 | |||
79 | /** | ||
80 | * Time of last validation | ||
81 | */ | ||
82 | struct GNUNET_TIME_Absolute last_validation; | ||
83 | |||
84 | /** | ||
85 | * Address is valid until | ||
86 | */ | ||
87 | struct GNUNET_TIME_Absolute valid_until; | ||
88 | |||
89 | /** | ||
90 | * Time of next validation | ||
91 | */ | ||
92 | struct GNUNET_TIME_Absolute next_validation; | ||
93 | |||
94 | /** | ||
95 | * state of validation process | ||
96 | */ | ||
97 | enum GNUNET_TRANSPORT_ValidationState state; | ||
98 | |||
99 | /** | ||
100 | * Tranport conversion handle | ||
101 | */ | ||
102 | struct GNUNET_TRANSPORT_AddressToStringContext *asc; | ||
103 | |||
104 | /** | ||
105 | * plugin name | ||
106 | */ | ||
107 | char *transport; | ||
108 | |||
109 | /** | ||
110 | * was the entry printed | ||
111 | */ | ||
112 | int printed; | ||
113 | }; | ||
114 | |||
115 | /** | ||
116 | * Struct to store information about peers in monitor mode | ||
117 | */ | ||
118 | struct MonitoredPeer | ||
119 | { | ||
120 | /** | ||
121 | * State of the peer | ||
122 | */ | ||
123 | enum GNUNET_TRANSPORT_PeerState state; | ||
124 | |||
125 | /** | ||
126 | * Timeout | ||
127 | */ | ||
128 | struct GNUNET_TIME_Absolute state_timeout; | ||
129 | |||
130 | /** | ||
131 | * The address to convert | ||
132 | */ | ||
133 | struct GNUNET_HELLO_Address *address; | ||
134 | }; | ||
135 | |||
136 | /** | ||
137 | * Context to store name resolutions for valiation | ||
138 | */ | ||
139 | struct PeerResolutionContext | ||
140 | { | ||
141 | /** | ||
142 | * Next in DLL | ||
143 | */ | ||
144 | struct PeerResolutionContext *next; | ||
145 | |||
146 | /** | ||
147 | * Prev in DLL | ||
148 | */ | ||
149 | struct PeerResolutionContext *prev; | ||
150 | |||
151 | /** | ||
152 | * The peer id | ||
153 | */ | ||
154 | struct GNUNET_PeerIdentity id; | ||
155 | |||
156 | /** | ||
157 | * address to resolve | ||
158 | */ | ||
159 | struct GNUNET_HELLO_Address *addrcp; | ||
160 | |||
161 | /** | ||
162 | * transport conversiion context | ||
163 | */ | ||
164 | struct GNUNET_TRANSPORT_AddressToStringContext *asc; | ||
165 | |||
166 | /** | ||
167 | * peer state | ||
168 | */ | ||
169 | enum GNUNET_TRANSPORT_PeerState state; | ||
170 | |||
171 | /** | ||
172 | * state timeout | ||
173 | */ | ||
174 | struct GNUNET_TIME_Absolute state_timeout; | ||
175 | |||
176 | /** | ||
177 | * transport plugin | ||
178 | */ | ||
179 | char *transport; | ||
180 | |||
181 | /** | ||
182 | * was the entry printed | ||
183 | */ | ||
184 | int printed; | ||
185 | }; | ||
186 | |||
187 | |||
188 | /** | ||
189 | * Context for a plugin test. | ||
190 | */ | ||
191 | struct TestContext | ||
192 | { | ||
193 | /** | ||
194 | * Previous in DLL | ||
195 | */ | ||
196 | struct TestContext *prev; | ||
197 | |||
198 | /** | ||
199 | * Next in DLL | ||
200 | */ | ||
201 | struct TestContext *next; | ||
202 | |||
203 | /** | ||
204 | * Handle to the active NAT test. | ||
205 | */ | ||
206 | struct GNUNET_NAT_Test *tst; | ||
207 | |||
208 | /** | ||
209 | * Task identifier for the timeout. | ||
210 | */ | ||
211 | GNUNET_SCHEDULER_TaskIdentifier tsk; | ||
212 | |||
213 | /** | ||
214 | * Name of plugin under test. | ||
215 | */ | ||
216 | char *name; | ||
217 | |||
218 | /** | ||
219 | * Bound port | ||
220 | */ | ||
221 | unsigned long long bnd_port; | ||
222 | |||
223 | /** | ||
224 | * Advertised ports | ||
225 | */ | ||
226 | unsigned long long adv_port; | ||
227 | |||
228 | }; | ||
229 | |||
230 | |||
231 | /** | ||
232 | * | ||
233 | */ | ||
234 | enum TestResult | ||
235 | { | ||
236 | /** | ||
237 | * NAT returned success | ||
238 | */ | ||
239 | NAT_TEST_SUCCESS = GNUNET_OK, | ||
240 | |||
241 | /** | ||
242 | * NAT returned failure | ||
243 | */ | ||
244 | NAT_TEST_FAIL = GNUNET_NO, | ||
245 | |||
246 | /** | ||
247 | * NAT returned failure while running test | ||
248 | */ | ||
249 | NAT_TEST_INTERNAL_FAIL = GNUNET_SYSERR, | ||
250 | |||
251 | /** | ||
252 | * We could not start the test | ||
253 | */ | ||
254 | NAT_TEST_FAILED_TO_START = 2, | ||
255 | |||
256 | /** | ||
257 | * We had a timeout while running the test | ||
258 | */ | ||
259 | NAT_TEST_TIMEOUT = 3 | ||
260 | }; | ||
261 | |||
262 | |||
263 | /** | ||
264 | * Benchmarking block size in KB | ||
265 | */ | ||
266 | #define BLOCKSIZE 4 | ||
267 | |||
268 | /** | ||
269 | * Which peer should we connect to? | ||
270 | */ | ||
271 | static char *cpid; | ||
272 | |||
273 | /** | ||
274 | * Handle to transport service. | ||
275 | */ | ||
276 | static struct GNUNET_TRANSPORT_Handle *handle; | ||
277 | |||
278 | /** | ||
279 | * Configuration handle | ||
280 | */ | ||
281 | static struct GNUNET_CONFIGURATION_Handle *cfg; | ||
282 | |||
283 | /** | ||
284 | * Try_connect handle | ||
285 | */ | ||
286 | struct GNUNET_TRANSPORT_TryConnectHandle *tc_handle; | ||
287 | |||
288 | /** | ||
289 | * Option -s. | ||
290 | */ | ||
291 | static int benchmark_send; | ||
292 | |||
293 | /** | ||
294 | * Option -b. | ||
295 | */ | ||
296 | static int benchmark_receive; | ||
297 | |||
298 | /** | ||
299 | * Option -l. | ||
300 | */ | ||
301 | static int benchmark_receive; | ||
302 | |||
303 | /** | ||
304 | * Option -i. | ||
305 | */ | ||
306 | static int iterate_connections; | ||
307 | |||
308 | /** | ||
309 | * Option -d. | ||
310 | */ | ||
311 | static int iterate_validation; | ||
312 | |||
313 | /** | ||
314 | * Option -a. | ||
315 | */ | ||
316 | static int iterate_all; | ||
317 | |||
318 | /** | ||
319 | * Option -t. | ||
320 | */ | ||
321 | static int test_configuration; | ||
322 | |||
323 | /** | ||
324 | * Option -c. | ||
325 | */ | ||
326 | static int monitor_connects; | ||
327 | |||
328 | /** | ||
329 | * Option -m. | ||
330 | */ | ||
331 | static int monitor_connections; | ||
332 | |||
333 | /** | ||
334 | * Option -f. | ||
335 | */ | ||
336 | static int monitor_validation; | ||
337 | |||
338 | /** | ||
339 | * Option -C. | ||
340 | */ | ||
341 | static int try_connect; | ||
342 | |||
343 | /** | ||
344 | * Option -D. | ||
345 | */ | ||
346 | static int try_disconnect; | ||
347 | |||
348 | /** | ||
349 | * Option -n. | ||
350 | */ | ||
351 | static int numeric; | ||
352 | |||
353 | /** | ||
354 | * Global return value (0 success). | ||
355 | */ | ||
356 | static int ret; | ||
357 | |||
358 | /** | ||
359 | * Current number of connections in monitor mode | ||
360 | */ | ||
361 | static int monitor_connect_counter; | ||
362 | |||
363 | /** | ||
364 | * Number of bytes of traffic we received so far. | ||
365 | */ | ||
366 | static unsigned long long traffic_received; | ||
367 | |||
368 | /** | ||
369 | * Number of bytes of traffic we sent so far. | ||
370 | */ | ||
371 | static unsigned long long traffic_sent; | ||
372 | |||
373 | /** | ||
374 | * Starting time of transmitting/receiving data. | ||
375 | */ | ||
376 | static struct GNUNET_TIME_Absolute start_time; | ||
377 | |||
378 | /** | ||
379 | * Handle for current transmission request. | ||
380 | */ | ||
381 | static struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
382 | |||
383 | /** | ||
384 | * Map storing information about monitored peers | ||
385 | */ | ||
386 | static struct GNUNET_CONTAINER_MultiPeerMap *monitored_peers; | ||
387 | |||
388 | /** | ||
389 | * | ||
390 | */ | ||
391 | static struct GNUNET_TRANSPORT_PeerMonitoringContext *pic; | ||
392 | |||
393 | /** | ||
394 | * | ||
395 | */ | ||
396 | static struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic; | ||
397 | |||
398 | /** | ||
399 | * Identity of the peer we transmit to / connect to. | ||
400 | * (equivalent to 'cpid' string). | ||
401 | */ | ||
402 | static struct GNUNET_PeerIdentity pid; | ||
403 | |||
404 | /** | ||
405 | * Task scheduled for cleanup / termination of the process. | ||
406 | */ | ||
407 | static GNUNET_SCHEDULER_TaskIdentifier end; | ||
408 | |||
409 | /** | ||
410 | * Task for operation timeout | ||
411 | */ | ||
412 | static GNUNET_SCHEDULER_TaskIdentifier op_timeout; | ||
413 | |||
414 | /** | ||
415 | * Selected level of verbosity. | ||
416 | */ | ||
417 | static int verbosity; | ||
418 | |||
419 | /** | ||
420 | * Resolver process handle. | ||
421 | */ | ||
422 | struct GNUNET_OS_Process *resolver; | ||
423 | |||
424 | /** | ||
425 | * Number of address resolutions pending | ||
426 | */ | ||
427 | static unsigned int address_resolutions; | ||
428 | |||
429 | /** | ||
430 | * Address resolutions pending in progress | ||
431 | */ | ||
432 | static unsigned int address_resolution_in_progress; | ||
433 | |||
434 | /** | ||
435 | * DLL for NAT Test Contexts: head | ||
436 | */ | ||
437 | struct TestContext *head; | ||
438 | |||
439 | /** | ||
440 | * DLL for NAT Test Contexts: tail | ||
441 | */ | ||
442 | struct TestContext *tail; | ||
443 | |||
444 | /** | ||
445 | * DLL: head of validation resolution entries | ||
446 | */ | ||
447 | static struct ValidationResolutionContext *vc_head; | ||
448 | |||
449 | /** | ||
450 | * DLL: tail of validation resolution entries | ||
451 | */ | ||
452 | static struct ValidationResolutionContext *vc_tail; | ||
453 | |||
454 | /** | ||
455 | * DLL: head of resolution entries | ||
456 | */ | ||
457 | static struct PeerResolutionContext *rc_head; | ||
458 | |||
459 | /** | ||
460 | * DLL: head of resolution entries | ||
461 | */ | ||
462 | static struct PeerResolutionContext *rc_tail; | ||
463 | |||
464 | |||
465 | static int | ||
466 | destroy_it (void *cls, | ||
467 | const struct GNUNET_PeerIdentity *key, | ||
468 | void *value) | ||
469 | { | ||
470 | struct MonitoredPeer *m = value; | ||
471 | |||
472 | GNUNET_assert (GNUNET_OK == | ||
473 | GNUNET_CONTAINER_multipeermap_remove (monitored_peers, | ||
474 | key, | ||
475 | value)); | ||
476 | GNUNET_free_non_null (m->address); | ||
477 | GNUNET_free (value); | ||
478 | return GNUNET_OK; | ||
479 | } | ||
480 | |||
481 | |||
482 | /** | ||
483 | * Task run in monitor mode when the user presses CTRL-C to abort. | ||
484 | * Stops monitoring activity. | ||
485 | * | ||
486 | * @param cls NULL | ||
487 | * @param tc scheduler context | ||
488 | */ | ||
489 | static void | ||
490 | shutdown_task (void *cls, | ||
491 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
492 | { | ||
493 | struct GNUNET_TIME_Relative duration; | ||
494 | struct ValidationResolutionContext *cur; | ||
495 | struct ValidationResolutionContext *next; | ||
496 | |||
497 | end = GNUNET_SCHEDULER_NO_TASK; | ||
498 | if (GNUNET_SCHEDULER_NO_TASK != op_timeout) | ||
499 | { | ||
500 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
501 | op_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
502 | } | ||
503 | if (NULL != tc_handle) | ||
504 | { | ||
505 | GNUNET_TRANSPORT_try_connect_cancel (tc_handle); | ||
506 | tc_handle = NULL; | ||
507 | } | ||
508 | if (NULL != pic) | ||
509 | { | ||
510 | GNUNET_TRANSPORT_monitor_peers_cancel (pic); | ||
511 | pic = NULL; | ||
512 | } | ||
513 | if (NULL != vic) | ||
514 | { | ||
515 | GNUNET_TRANSPORT_monitor_validation_entries_cancel (vic); | ||
516 | vic = NULL; | ||
517 | } | ||
518 | |||
519 | next = vc_head; | ||
520 | for (cur = next; NULL != cur; cur = next) | ||
521 | { | ||
522 | next = cur->next; | ||
523 | |||
524 | GNUNET_TRANSPORT_address_to_string_cancel (cur->asc); | ||
525 | GNUNET_CONTAINER_DLL_remove (vc_head, vc_tail, cur); | ||
526 | GNUNET_free (cur->transport); | ||
527 | GNUNET_HELLO_address_free (cur->addrcp); | ||
528 | GNUNET_free (cur); | ||
529 | } | ||
530 | |||
531 | if (NULL != th) | ||
532 | { | ||
533 | GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); | ||
534 | th = NULL; | ||
535 | } | ||
536 | if (NULL != handle) | ||
537 | { | ||
538 | GNUNET_TRANSPORT_disconnect (handle); | ||
539 | handle = NULL; | ||
540 | } | ||
541 | if (benchmark_send) | ||
542 | { | ||
543 | duration = GNUNET_TIME_absolute_get_duration (start_time); | ||
544 | FPRINTF (stdout, | ||
545 | _("Transmitted %llu bytes/s (%llu bytes in %s)\n"), | ||
546 | 1000LL * 1000LL * traffic_sent / (1 + duration.rel_value_us), | ||
547 | traffic_sent, | ||
548 | GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); | ||
549 | } | ||
550 | if (benchmark_receive) | ||
551 | { | ||
552 | duration = GNUNET_TIME_absolute_get_duration (start_time); | ||
553 | FPRINTF (stdout, | ||
554 | _("Received %llu bytes/s (%llu bytes in %s)\n"), | ||
555 | 1000LL * 1000LL * traffic_received / (1 + duration.rel_value_us), | ||
556 | traffic_received, | ||
557 | GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); | ||
558 | } | ||
559 | |||
560 | if (NULL != monitored_peers) | ||
561 | { | ||
562 | GNUNET_CONTAINER_multipeermap_iterate (monitored_peers, &destroy_it, NULL); | ||
563 | GNUNET_CONTAINER_multipeermap_destroy (monitored_peers); | ||
564 | monitored_peers = NULL; | ||
565 | } | ||
566 | } | ||
567 | |||
568 | |||
569 | static void | ||
570 | operation_timeout (void *cls, | ||
571 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
572 | { | ||
573 | struct PeerResolutionContext *cur; | ||
574 | struct PeerResolutionContext *next; | ||
575 | op_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
576 | if ((try_connect) || (benchmark_send) || (benchmark_receive)) | ||
577 | { | ||
578 | FPRINTF (stdout, | ||
579 | _("Failed to connect to `%s'\n"), | ||
580 | GNUNET_i2s_full (&pid)); | ||
581 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
582 | GNUNET_SCHEDULER_cancel (end); | ||
583 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
584 | ret = 1; | ||
585 | return; | ||
586 | } | ||
587 | if (iterate_connections) | ||
588 | { | ||
589 | next = rc_head; | ||
590 | while (NULL != (cur = next)) | ||
591 | { | ||
592 | next = cur->next; | ||
593 | FPRINTF (stdout, | ||
594 | _("Failed to resolve address for peer `%s'\n"), | ||
595 | GNUNET_i2s (&cur->addrcp->peer)); | ||
596 | |||
597 | GNUNET_CONTAINER_DLL_remove(rc_head, rc_tail, cur); | ||
598 | GNUNET_TRANSPORT_address_to_string_cancel (cur->asc); | ||
599 | GNUNET_free(cur->transport); | ||
600 | GNUNET_free(cur->addrcp); | ||
601 | GNUNET_free(cur); | ||
602 | |||
603 | } | ||
604 | FPRINTF (stdout, | ||
605 | "%s", | ||
606 | _("Failed to list connections, timeout occured\n")); | ||
607 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
608 | GNUNET_SCHEDULER_cancel (end); | ||
609 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
610 | ret = 1; | ||
611 | return; | ||
612 | } | ||
613 | } | ||
614 | |||
615 | |||
616 | static void | ||
617 | run_nat_test (); | ||
618 | |||
619 | |||
620 | /** | ||
621 | * Display the result of the test. | ||
622 | * | ||
623 | * @param tc test context | ||
624 | * @param result #GNUNET_YES on success | ||
625 | */ | ||
626 | static void | ||
627 | display_test_result (struct TestContext *tc, | ||
628 | enum TestResult result) | ||
629 | { | ||
630 | switch (result) { | ||
631 | case NAT_TEST_FAIL: | ||
632 | FPRINTF (stderr, | ||
633 | _("Configuration for plugin `%s' did not work!\n"), | ||
634 | tc->name); | ||
635 | break; | ||
636 | case NAT_TEST_SUCCESS: | ||
637 | FPRINTF (stderr, | ||
638 | _("Configuration for plugin `%s' did work!\n"), | ||
639 | tc->name); | ||
640 | break; | ||
641 | case NAT_TEST_INTERNAL_FAIL: | ||
642 | FPRINTF (stderr, | ||
643 | _("Internal NAT error while running test for plugin `%s'\n"), | ||
644 | tc->name); | ||
645 | break; | ||
646 | case NAT_TEST_FAILED_TO_START: | ||
647 | FPRINTF (stderr, | ||
648 | _("Failed to start NAT test for plugin `%s'\n"), | ||
649 | tc->name); | ||
650 | break; | ||
651 | case NAT_TEST_TIMEOUT: | ||
652 | FPRINTF (stderr, | ||
653 | _("Timeout while waiting for result of NAT test for plugin `%s'\n"), | ||
654 | tc->name); | ||
655 | break; | ||
656 | default: | ||
657 | break; | ||
658 | } | ||
659 | |||
660 | if (GNUNET_YES != result) | ||
661 | { | ||
662 | FPRINTF (stderr, | ||
663 | _("Configuration for plugin `%s' did not work!\n"), | ||
664 | tc->name); | ||
665 | } | ||
666 | else | ||
667 | { | ||
668 | FPRINTF (stderr, | ||
669 | _("Configuration for plugin `%s' is working!\n"), | ||
670 | tc->name); | ||
671 | } | ||
672 | if (GNUNET_SCHEDULER_NO_TASK != tc->tsk) | ||
673 | { | ||
674 | GNUNET_SCHEDULER_cancel (tc->tsk); | ||
675 | tc->tsk = GNUNET_SCHEDULER_NO_TASK; | ||
676 | } | ||
677 | if (NULL != tc->tst) | ||
678 | { | ||
679 | GNUNET_NAT_test_stop (tc->tst); | ||
680 | tc->tst = NULL; | ||
681 | } | ||
682 | |||
683 | GNUNET_CONTAINER_DLL_remove (head, tail, tc); | ||
684 | GNUNET_free (tc->name); | ||
685 | GNUNET_free (tc); | ||
686 | |||
687 | if ((NULL == head) && (NULL != resolver)) | ||
688 | { | ||
689 | GNUNET_break (0 == GNUNET_OS_process_kill (resolver, | ||
690 | GNUNET_TERM_SIG)); | ||
691 | GNUNET_OS_process_destroy (resolver); | ||
692 | resolver = NULL; | ||
693 | } | ||
694 | if (NULL != head) | ||
695 | run_nat_test (); | ||
696 | } | ||
697 | |||
698 | /** | ||
699 | * Function called by NAT to report the outcome of the nat-test. | ||
700 | * Clean up and update GUI. | ||
701 | * | ||
702 | * @param cls test context | ||
703 | * @param result status code | ||
704 | */ | ||
705 | static void | ||
706 | result_callback (void *cls, | ||
707 | enum GNUNET_NAT_StatusCode result) | ||
708 | { | ||
709 | struct TestContext *tc = cls; | ||
710 | |||
711 | display_test_result (tc, result); | ||
712 | } | ||
713 | |||
714 | |||
715 | /** | ||
716 | * Resolve address we got a validation state for to a string. | ||
717 | * | ||
718 | * @param id peer identity the address is for | ||
719 | * @param address the address itself | ||
720 | * @param numeric #GNUNET_YES to disable DNS, #GNUNET_NO to try reverse lookup | ||
721 | * @param last_validation when was the address validated last | ||
722 | * @param valid_until until when is the address valid | ||
723 | * @param next_validation when will we try to revalidate the address next | ||
724 | * @param state where are we in the validation state machine | ||
725 | */ | ||
726 | static void | ||
727 | resolve_validation_address (const struct GNUNET_PeerIdentity *id, | ||
728 | const struct GNUNET_HELLO_Address *address, | ||
729 | int numeric, | ||
730 | struct GNUNET_TIME_Absolute last_validation, | ||
731 | struct GNUNET_TIME_Absolute valid_until, | ||
732 | struct GNUNET_TIME_Absolute next_validation, | ||
733 | enum GNUNET_TRANSPORT_ValidationState state); | ||
734 | |||
735 | |||
736 | /** | ||
737 | * Function to call with a textual representation of an address. This | ||
738 | * function will be called several times with different possible | ||
739 | * textual representations, and a last time with @a address being NULL | ||
740 | * to signal the end of the iteration. Note that @a address NULL | ||
741 | * always is the last call, regardless of the value in @a res. | ||
742 | * | ||
743 | * @param cls closure | ||
744 | * @param address NULL on end of iteration, | ||
745 | * otherwise 0-terminated printable UTF-8 string, | ||
746 | * in particular an empty string if @a res is #GNUNET_NO | ||
747 | * @param res result of the address to string conversion: | ||
748 | * if #GNUNET_OK: conversion successful | ||
749 | * if #GNUNET_NO: address was invalid (or not supported) | ||
750 | * if #GNUNET_SYSERR: communication error (IPC error) | ||
751 | */ | ||
752 | static void | ||
753 | process_validation_string (void *cls, | ||
754 | const char *address, | ||
755 | int res) | ||
756 | { | ||
757 | struct ValidationResolutionContext *vc = cls; | ||
758 | char *s_valid; | ||
759 | char *s_last; | ||
760 | char *s_next; | ||
761 | |||
762 | if (NULL != address) | ||
763 | { | ||
764 | if (GNUNET_SYSERR == res) | ||
765 | { | ||
766 | FPRINTF (stderr, | ||
767 | "Failed to convert address for peer `%s' plugin `%s' length %lu to string \n", | ||
768 | GNUNET_i2s (&vc->id), | ||
769 | vc->addrcp->transport_name, | ||
770 | vc->addrcp->address_length); | ||
771 | } | ||
772 | if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us == vc->valid_until.abs_value_us) | ||
773 | s_valid = GNUNET_strdup ("never"); | ||
774 | else | ||
775 | s_valid = GNUNET_strdup (GNUNET_STRINGS_absolute_time_to_string (vc->valid_until)); | ||
776 | |||
777 | if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us == vc->last_validation.abs_value_us) | ||
778 | s_last = GNUNET_strdup ("never"); | ||
779 | else | ||
780 | s_last = GNUNET_strdup (GNUNET_STRINGS_absolute_time_to_string (vc->last_validation)); | ||
781 | |||
782 | if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us == vc->next_validation.abs_value_us) | ||
783 | s_next = GNUNET_strdup ("never"); | ||
784 | else | ||
785 | s_next = GNUNET_strdup (GNUNET_STRINGS_absolute_time_to_string (vc->next_validation)); | ||
786 | |||
787 | FPRINTF (stdout, | ||
788 | _("Peer `%s' %s %s\n\t%s%s\n\t%s%s\n\t%s%s\n"), | ||
789 | GNUNET_i2s (&vc->id), | ||
790 | (GNUNET_OK == res) ? address : "<invalid address>", | ||
791 | (monitor_validation) ? GNUNET_TRANSPORT_vs2s (vc->state) : "", | ||
792 | "Valid until : ", s_valid, | ||
793 | "Last validation: ",s_last, | ||
794 | "Next validation: ", s_next); | ||
795 | GNUNET_free (s_valid); | ||
796 | GNUNET_free (s_last); | ||
797 | GNUNET_free (s_next); | ||
798 | vc->printed = GNUNET_YES; | ||
799 | return; | ||
800 | } | ||
801 | /* last call, we are done */ | ||
802 | GNUNET_assert (address_resolutions > 0); | ||
803 | address_resolutions--; | ||
804 | if ( (GNUNET_SYSERR == res) && | ||
805 | (GNUNET_NO == vc->printed)) | ||
806 | { | ||
807 | if (numeric == GNUNET_NO) | ||
808 | { | ||
809 | /* Failed to resolve address, try numeric lookup | ||
810 | (note: this should be unnecessary, as | ||
811 | transport should fallback to numeric lookup | ||
812 | internally if DNS takes too long anyway) */ | ||
813 | resolve_validation_address (&vc->id, | ||
814 | vc->addrcp, | ||
815 | GNUNET_NO, | ||
816 | vc->last_validation, | ||
817 | vc->valid_until, | ||
818 | vc->next_validation, | ||
819 | vc->state); | ||
820 | } | ||
821 | else | ||
822 | { | ||
823 | FPRINTF (stdout, | ||
824 | _("Peer `%s' %s `%s' \n"), | ||
825 | GNUNET_i2s (&vc->id), | ||
826 | "<unable to resolve address>", | ||
827 | GNUNET_TRANSPORT_vs2s (vc->state)); | ||
828 | } | ||
829 | } | ||
830 | GNUNET_free (vc->transport); | ||
831 | GNUNET_free (vc->addrcp); | ||
832 | GNUNET_CONTAINER_DLL_remove (vc_head, vc_tail, vc); | ||
833 | GNUNET_free (vc); | ||
834 | if ((0 == address_resolutions) && (iterate_validation)) | ||
835 | { | ||
836 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
837 | { | ||
838 | GNUNET_SCHEDULER_cancel (end); | ||
839 | end = GNUNET_SCHEDULER_NO_TASK; | ||
840 | } | ||
841 | if (GNUNET_SCHEDULER_NO_TASK != op_timeout) | ||
842 | { | ||
843 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
844 | op_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
845 | } | ||
846 | ret = 0; | ||
847 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
848 | } | ||
849 | } | ||
850 | |||
851 | |||
852 | /** | ||
853 | * Resolve address we got a validation state for to a string. | ||
854 | * | ||
855 | * @param id peer identity the address is for | ||
856 | * @param address the address itself | ||
857 | * @param numeric #GNUNET_YES to disable DNS, #GNUNET_NO to try reverse lookup | ||
858 | * @param last_validation when was the address validated last | ||
859 | * @param valid_until until when is the address valid | ||
860 | * @param next_validation when will we try to revalidate the address next | ||
861 | * @param state where are we in the validation state machine | ||
862 | */ | ||
863 | static void | ||
864 | resolve_validation_address (const struct GNUNET_PeerIdentity *id, | ||
865 | const struct GNUNET_HELLO_Address *address, | ||
866 | int numeric, | ||
867 | struct GNUNET_TIME_Absolute last_validation, | ||
868 | struct GNUNET_TIME_Absolute valid_until, | ||
869 | struct GNUNET_TIME_Absolute next_validation, | ||
870 | enum GNUNET_TRANSPORT_ValidationState state) | ||
871 | { | ||
872 | struct ValidationResolutionContext *vc; | ||
873 | |||
874 | vc = GNUNET_new (struct ValidationResolutionContext); | ||
875 | GNUNET_assert(NULL != vc); | ||
876 | GNUNET_CONTAINER_DLL_insert(vc_head, vc_tail, vc); | ||
877 | address_resolutions++; | ||
878 | |||
879 | vc->id = (*id); | ||
880 | vc->transport = GNUNET_strdup(address->transport_name); | ||
881 | vc->addrcp = GNUNET_HELLO_address_copy (address); | ||
882 | vc->printed = GNUNET_NO; | ||
883 | vc->state = state; | ||
884 | vc->last_validation = last_validation; | ||
885 | vc->valid_until = valid_until; | ||
886 | vc->next_validation = next_validation; | ||
887 | |||
888 | /* Resolve address to string */ | ||
889 | vc->asc = GNUNET_TRANSPORT_address_to_string (cfg, | ||
890 | address, | ||
891 | numeric, | ||
892 | RESOLUTION_TIMEOUT, | ||
893 | &process_validation_string, vc); | ||
894 | } | ||
895 | |||
896 | |||
897 | /** | ||
898 | * Resolve address we got a validation state for to a string. | ||
899 | * | ||
900 | * @param cls NULL | ||
901 | * @param peer peer identity the address is for | ||
902 | * @param address the address itself | ||
903 | * @param last_validation when was the address validated last | ||
904 | * @param valid_until until when is the address valid | ||
905 | * @param next_validation when will we try to revalidate the address next | ||
906 | * @param state where are we in the validation state machine | ||
907 | */ | ||
908 | static void | ||
909 | process_validation_cb (void *cls, | ||
910 | const struct GNUNET_PeerIdentity *peer, | ||
911 | const struct GNUNET_HELLO_Address *address, | ||
912 | struct GNUNET_TIME_Absolute last_validation, | ||
913 | struct GNUNET_TIME_Absolute valid_until, | ||
914 | struct GNUNET_TIME_Absolute next_validation, | ||
915 | enum GNUNET_TRANSPORT_ValidationState state) | ||
916 | { | ||
917 | if ((NULL == peer) && (NULL == address)) | ||
918 | { | ||
919 | if (monitor_validation) | ||
920 | { | ||
921 | FPRINTF (stdout, | ||
922 | "%s", | ||
923 | _("Monitor disconnected from transport service. Reconnecting.\n")); | ||
924 | return; | ||
925 | } | ||
926 | |||
927 | /* done */ | ||
928 | vic = NULL; | ||
929 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
930 | GNUNET_SCHEDULER_cancel (end); | ||
931 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
932 | return; | ||
933 | } | ||
934 | if ((NULL == peer) || (NULL == address)) | ||
935 | { | ||
936 | /* invalid response */ | ||
937 | vic = NULL; | ||
938 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
939 | GNUNET_SCHEDULER_cancel (end); | ||
940 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
941 | return; | ||
942 | } | ||
943 | resolve_validation_address (peer, | ||
944 | address, | ||
945 | numeric, | ||
946 | last_validation, | ||
947 | valid_until, | ||
948 | next_validation, | ||
949 | state); | ||
950 | } | ||
951 | |||
952 | |||
953 | static void | ||
954 | run_nat_test () | ||
955 | { | ||
956 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
957 | "Running test for plugin `%s' using bind port %u and advertised port %u \n", | ||
958 | head->name, | ||
959 | (uint16_t) head->bnd_port, | ||
960 | (uint16_t) head->adv_port); | ||
961 | |||
962 | head->tst = GNUNET_NAT_test_start (cfg, | ||
963 | (0 == strcasecmp (head->name, "udp")) ? GNUNET_NO : GNUNET_YES, | ||
964 | (uint16_t) head->bnd_port, | ||
965 | (uint16_t) head->adv_port, | ||
966 | TIMEOUT, | ||
967 | &result_callback, head); | ||
968 | } | ||
969 | |||
970 | |||
971 | /** | ||
972 | * Test our plugin's configuration (NAT traversal, etc.). | ||
973 | * | ||
974 | * @param cfg configuration to test | ||
975 | */ | ||
976 | static void | ||
977 | do_test_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
978 | { | ||
979 | char *plugins; | ||
980 | char *tok; | ||
981 | unsigned long long bnd_port; | ||
982 | unsigned long long adv_port; | ||
983 | struct TestContext *tc; | ||
984 | char *binary; | ||
985 | |||
986 | if (GNUNET_OK | ||
987 | != GNUNET_CONFIGURATION_get_value_string (cfg, "transport", "plugins", | ||
988 | &plugins)) | ||
989 | { | ||
990 | FPRINTF (stderr, "%s", _ | ||
991 | ("No transport plugins configured, peer will never communicate\n")); | ||
992 | ret = 4; | ||
993 | return; | ||
994 | } | ||
995 | |||
996 | for (tok = strtok (plugins, " "); tok != NULL ; tok = strtok (NULL, " ")) | ||
997 | { | ||
998 | char section[12 + strlen (tok)]; | ||
999 | GNUNET_snprintf (section, sizeof(section), "transport-%s", tok); | ||
1000 | if (GNUNET_OK | ||
1001 | != GNUNET_CONFIGURATION_get_value_number (cfg, section, "PORT", | ||
1002 | &bnd_port)) | ||
1003 | { | ||
1004 | FPRINTF (stderr, | ||
1005 | _("No port configured for plugin `%s', cannot test it\n"), tok); | ||
1006 | continue; | ||
1007 | } | ||
1008 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, section, | ||
1009 | "ADVERTISED_PORT", &adv_port)) | ||
1010 | adv_port = bnd_port; | ||
1011 | |||
1012 | tc = GNUNET_new (struct TestContext); | ||
1013 | tc->name = GNUNET_strdup (tok); | ||
1014 | tc->adv_port = adv_port; | ||
1015 | tc->bnd_port = bnd_port; | ||
1016 | GNUNET_CONTAINER_DLL_insert_tail (head, tail, tc); | ||
1017 | } | ||
1018 | GNUNET_free(plugins); | ||
1019 | |||
1020 | if ((NULL != head) && (NULL == resolver)) | ||
1021 | { | ||
1022 | binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver"); | ||
1023 | resolver = GNUNET_OS_start_process (GNUNET_YES, | ||
1024 | GNUNET_OS_INHERIT_STD_OUT_AND_ERR, | ||
1025 | NULL, NULL, NULL, | ||
1026 | binary, | ||
1027 | "gnunet-service-resolver", NULL); | ||
1028 | if (NULL == resolver) | ||
1029 | { | ||
1030 | FPRINTF (stderr, _("Failed to start resolver!\n")); | ||
1031 | return; | ||
1032 | } | ||
1033 | |||
1034 | GNUNET_free(binary); | ||
1035 | GNUNET_RESOLVER_connect (cfg); | ||
1036 | run_nat_test (); | ||
1037 | } | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | /** | ||
1042 | * Function called to notify a client about the socket | ||
1043 | * begin ready to queue more data. @a buf will be | ||
1044 | * NULL and @a size zero if the socket was closed for | ||
1045 | * writing in the meantime. | ||
1046 | * | ||
1047 | * @param cls closure | ||
1048 | * @param size number of bytes available in @a buf | ||
1049 | * @param buf where the callee should write the message | ||
1050 | * @return number of bytes written to @a buf | ||
1051 | */ | ||
1052 | static size_t | ||
1053 | transmit_data (void *cls, | ||
1054 | size_t size, | ||
1055 | void *buf) | ||
1056 | { | ||
1057 | struct GNUNET_MessageHeader *m = buf; | ||
1058 | |||
1059 | if ((NULL == buf) || (0 == size)) | ||
1060 | { | ||
1061 | th = NULL; | ||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | GNUNET_assert(size >= sizeof(struct GNUNET_MessageHeader)); | ||
1066 | GNUNET_assert(size < GNUNET_SERVER_MAX_MESSAGE_SIZE); | ||
1067 | m->size = ntohs (size); | ||
1068 | m->type = ntohs (GNUNET_MESSAGE_TYPE_DUMMY); | ||
1069 | memset (&m[1], 52, size - sizeof(struct GNUNET_MessageHeader)); | ||
1070 | traffic_sent += size; | ||
1071 | th = GNUNET_TRANSPORT_notify_transmit_ready (handle, &pid, | ||
1072 | BLOCKSIZE * 1024, | ||
1073 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1074 | &transmit_data, NULL); | ||
1075 | if (verbosity > 0) | ||
1076 | FPRINTF (stdout, _("Transmitting %u bytes to %s\n"), (unsigned int) size, | ||
1077 | GNUNET_i2s (&pid)); | ||
1078 | return size; | ||
1079 | } | ||
1080 | |||
1081 | |||
1082 | /** | ||
1083 | * Function called to notify transport users that another | ||
1084 | * peer connected to us. | ||
1085 | * | ||
1086 | * @param cls closure | ||
1087 | * @param peer the peer that connected | ||
1088 | */ | ||
1089 | static void | ||
1090 | notify_connect (void *cls, | ||
1091 | const struct GNUNET_PeerIdentity *peer) | ||
1092 | { | ||
1093 | if (0 != memcmp (&pid, peer, sizeof(struct GNUNET_PeerIdentity))) | ||
1094 | return; | ||
1095 | ret = 0; | ||
1096 | if (try_connect) | ||
1097 | { | ||
1098 | /* all done, terminate instantly */ | ||
1099 | FPRINTF (stdout, _("Successfully connected to `%s'\n"), | ||
1100 | GNUNET_i2s_full (peer)); | ||
1101 | ret = 0; | ||
1102 | |||
1103 | if (GNUNET_SCHEDULER_NO_TASK != op_timeout) | ||
1104 | { | ||
1105 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
1106 | op_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
1107 | } | ||
1108 | |||
1109 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
1110 | GNUNET_SCHEDULER_cancel (end); | ||
1111 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
1112 | return; | ||
1113 | } | ||
1114 | if (benchmark_send) | ||
1115 | { | ||
1116 | if (GNUNET_SCHEDULER_NO_TASK != op_timeout) | ||
1117 | { | ||
1118 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
1119 | op_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
1120 | } | ||
1121 | if (verbosity > 0) | ||
1122 | FPRINTF (stdout, | ||
1123 | _("Successfully connected to `%s', starting to send benchmark data in %u Kb blocks\n"), | ||
1124 | GNUNET_i2s (&pid), BLOCKSIZE); | ||
1125 | start_time = GNUNET_TIME_absolute_get (); | ||
1126 | if (NULL == th) | ||
1127 | th = GNUNET_TRANSPORT_notify_transmit_ready (handle, peer, | ||
1128 | BLOCKSIZE * 1024, | ||
1129 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1130 | &transmit_data, | ||
1131 | NULL); | ||
1132 | else | ||
1133 | GNUNET_break(0); | ||
1134 | return; | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | /** | ||
1140 | * Function called to notify transport users that another | ||
1141 | * peer disconnected from us. | ||
1142 | * | ||
1143 | * @param cls closure | ||
1144 | * @param peer the peer that disconnected | ||
1145 | */ | ||
1146 | static void | ||
1147 | notify_disconnect (void *cls, | ||
1148 | const struct GNUNET_PeerIdentity *peer) | ||
1149 | { | ||
1150 | if (0 != memcmp (&pid, peer, sizeof(struct GNUNET_PeerIdentity))) | ||
1151 | return; | ||
1152 | |||
1153 | if (try_disconnect) | ||
1154 | { | ||
1155 | /* all done, terminate instantly */ | ||
1156 | FPRINTF (stdout, _("Successfully disconnected from `%s'\n"), | ||
1157 | GNUNET_i2s_full (peer)); | ||
1158 | ret = 0; | ||
1159 | |||
1160 | if (GNUNET_SCHEDULER_NO_TASK != op_timeout) | ||
1161 | { | ||
1162 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
1163 | op_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
1164 | } | ||
1165 | |||
1166 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
1167 | GNUNET_SCHEDULER_cancel (end); | ||
1168 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
1169 | return; | ||
1170 | } | ||
1171 | |||
1172 | if (NULL != th) | ||
1173 | { | ||
1174 | GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); | ||
1175 | th = NULL; | ||
1176 | } | ||
1177 | if (benchmark_send) | ||
1178 | { | ||
1179 | FPRINTF (stdout, _("Disconnected from peer `%s' while benchmarking\n"), | ||
1180 | GNUNET_i2s (&pid)); | ||
1181 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
1182 | GNUNET_SCHEDULER_cancel (end); | ||
1183 | return; | ||
1184 | } | ||
1185 | } | ||
1186 | |||
1187 | |||
1188 | /** | ||
1189 | * Function called to notify transport users that another | ||
1190 | * peer connected to us. | ||
1191 | * | ||
1192 | * @param cls closure | ||
1193 | * @param peer the peer that connected | ||
1194 | */ | ||
1195 | static void | ||
1196 | monitor_notify_connect (void *cls, | ||
1197 | const struct GNUNET_PeerIdentity *peer) | ||
1198 | { | ||
1199 | monitor_connect_counter++; | ||
1200 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | ||
1201 | const char *now_str = GNUNET_STRINGS_absolute_time_to_string (now); | ||
1202 | |||
1203 | FPRINTF (stdout, | ||
1204 | _("%24s: %-17s %4s (%u connections in total)\n"), | ||
1205 | now_str, | ||
1206 | _("Connected to"), | ||
1207 | GNUNET_i2s (peer), | ||
1208 | monitor_connect_counter); | ||
1209 | } | ||
1210 | |||
1211 | |||
1212 | /** | ||
1213 | * Function called to notify transport users that another | ||
1214 | * peer disconnected from us. | ||
1215 | * | ||
1216 | * @param cls closure | ||
1217 | * @param peer the peer that disconnected | ||
1218 | */ | ||
1219 | static void | ||
1220 | monitor_notify_disconnect (void *cls, | ||
1221 | const struct GNUNET_PeerIdentity *peer) | ||
1222 | { | ||
1223 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | ||
1224 | const char *now_str = GNUNET_STRINGS_absolute_time_to_string (now); | ||
1225 | |||
1226 | GNUNET_assert(monitor_connect_counter > 0); | ||
1227 | monitor_connect_counter--; | ||
1228 | |||
1229 | FPRINTF (stdout, | ||
1230 | _("%24s: %-17s %4s (%u connections in total)\n"), | ||
1231 | now_str, | ||
1232 | _("Disconnected from"), | ||
1233 | GNUNET_i2s (peer), | ||
1234 | monitor_connect_counter); | ||
1235 | } | ||
1236 | |||
1237 | |||
1238 | /** | ||
1239 | * Function called by the transport for each received message. | ||
1240 | * | ||
1241 | * @param cls closure | ||
1242 | * @param peer (claimed) identity of the other peer | ||
1243 | * @param message the message | ||
1244 | */ | ||
1245 | static void | ||
1246 | notify_receive (void *cls, | ||
1247 | const struct GNUNET_PeerIdentity *peer, | ||
1248 | const struct GNUNET_MessageHeader *message) | ||
1249 | { | ||
1250 | if (benchmark_receive) | ||
1251 | { | ||
1252 | if (GNUNET_MESSAGE_TYPE_DUMMY != ntohs (message->type)) | ||
1253 | return; | ||
1254 | if (verbosity > 0) | ||
1255 | FPRINTF (stdout, | ||
1256 | _("Received %u bytes from %s\n"), | ||
1257 | (unsigned int) ntohs (message->size), | ||
1258 | GNUNET_i2s (peer)); | ||
1259 | |||
1260 | if (traffic_received == 0) | ||
1261 | start_time = GNUNET_TIME_absolute_get (); | ||
1262 | traffic_received += ntohs (message->size); | ||
1263 | return; | ||
1264 | } | ||
1265 | } | ||
1266 | |||
1267 | |||
1268 | static void | ||
1269 | resolve_peer_address (const struct GNUNET_PeerIdentity *id, | ||
1270 | const struct GNUNET_HELLO_Address *address, | ||
1271 | int numeric, | ||
1272 | enum GNUNET_TRANSPORT_PeerState state, | ||
1273 | struct GNUNET_TIME_Absolute state_timeout); | ||
1274 | |||
1275 | |||
1276 | static void | ||
1277 | print_info (const struct GNUNET_PeerIdentity *id, | ||
1278 | const char *transport, | ||
1279 | const char *addr, | ||
1280 | enum GNUNET_TRANSPORT_PeerState state, | ||
1281 | struct GNUNET_TIME_Absolute state_timeout) | ||
1282 | { | ||
1283 | |||
1284 | if ( ((GNUNET_YES == iterate_connections) && (GNUNET_YES == iterate_all)) || | ||
1285 | (GNUNET_YES == monitor_connections)) | ||
1286 | { | ||
1287 | FPRINTF (stdout, | ||
1288 | _("Peer `%s': %s %s in state `%s' until %s\n"), | ||
1289 | GNUNET_i2s (id), | ||
1290 | (NULL == transport) ? "<none>" : transport, | ||
1291 | (NULL == transport) ? "<none>" : addr, | ||
1292 | GNUNET_TRANSPORT_ps2s (state), | ||
1293 | GNUNET_STRINGS_absolute_time_to_string (state_timeout)); | ||
1294 | } | ||
1295 | else if ( (GNUNET_YES == iterate_connections) && | ||
1296 | (GNUNET_TRANSPORT_is_connected(state))) | ||
1297 | { | ||
1298 | /* Only connected peers, skip state */ | ||
1299 | FPRINTF (stdout, | ||
1300 | _("Peer `%s': %s %s\n"), | ||
1301 | GNUNET_i2s (id), | ||
1302 | transport, | ||
1303 | addr); | ||
1304 | } | ||
1305 | } | ||
1306 | |||
1307 | |||
1308 | /** | ||
1309 | * Function called with a textual representation of an address. This | ||
1310 | * function will be called several times with different possible | ||
1311 | * textual representations, and a last time with @a address being NULL | ||
1312 | * to signal the end of the iteration. Note that @a address NULL | ||
1313 | * always is the last call, regardless of the value in @a res. | ||
1314 | * | ||
1315 | * @param cls closure | ||
1316 | * @param address NULL on end of iteration, | ||
1317 | * otherwise 0-terminated printable UTF-8 string, | ||
1318 | * in particular an empty string if @a res is #GNUNET_NO | ||
1319 | * @param res result of the address to string conversion: | ||
1320 | * if #GNUNET_OK: conversion successful | ||
1321 | * if #GNUNET_NO: address was invalid (or not supported) | ||
1322 | * if #GNUNET_SYSERR: communication error (IPC error) | ||
1323 | */ | ||
1324 | static void | ||
1325 | process_peer_string (void *cls, | ||
1326 | const char *address, | ||
1327 | int res) | ||
1328 | { | ||
1329 | struct PeerResolutionContext *rc = cls; | ||
1330 | |||
1331 | if (NULL != address) | ||
1332 | { | ||
1333 | if (GNUNET_SYSERR == res) | ||
1334 | { | ||
1335 | FPRINTF (stderr, | ||
1336 | "Failed to convert address for peer `%s' plugin `%s' length %lu to string \n", | ||
1337 | GNUNET_i2s (&rc->id), | ||
1338 | rc->addrcp->transport_name, | ||
1339 | rc->addrcp->address_length); | ||
1340 | print_info (&rc->id, | ||
1341 | rc->transport, | ||
1342 | NULL, | ||
1343 | rc->state, | ||
1344 | rc->state_timeout); | ||
1345 | rc->printed = GNUNET_YES; | ||
1346 | return; | ||
1347 | } | ||
1348 | if (GNUNET_OK == res) | ||
1349 | { | ||
1350 | print_info (&rc->id, | ||
1351 | rc->transport, | ||
1352 | address, | ||
1353 | rc->state, | ||
1354 | rc->state_timeout); | ||
1355 | rc->printed = GNUNET_YES; | ||
1356 | return; /* Wait for done call */ | ||
1357 | } | ||
1358 | /* GNUNET_NO == res: ignore, was simply not supported */ | ||
1359 | return; | ||
1360 | } | ||
1361 | /* NULL == address, last call, we are done */ | ||
1362 | |||
1363 | GNUNET_assert (address_resolutions > 0); | ||
1364 | address_resolutions--; | ||
1365 | if (GNUNET_NO == rc->printed) | ||
1366 | { | ||
1367 | if (numeric == GNUNET_NO) | ||
1368 | { | ||
1369 | /* Failed to resolve address, try numeric lookup | ||
1370 | (note: this should not be needed, as transport | ||
1371 | should fallback to numeric conversion if DNS takes | ||
1372 | too long) */ | ||
1373 | resolve_peer_address (&rc->id, | ||
1374 | rc->addrcp, | ||
1375 | GNUNET_YES, | ||
1376 | rc->state, | ||
1377 | rc->state_timeout); | ||
1378 | } | ||
1379 | else | ||
1380 | { | ||
1381 | print_info (&rc->id, | ||
1382 | rc->transport, | ||
1383 | NULL, | ||
1384 | rc->state, | ||
1385 | rc->state_timeout); | ||
1386 | } | ||
1387 | } | ||
1388 | GNUNET_free (rc->transport); | ||
1389 | GNUNET_free (rc->addrcp); | ||
1390 | GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, rc); | ||
1391 | GNUNET_free (rc); | ||
1392 | if ((0 == address_resolutions) && (iterate_connections)) | ||
1393 | { | ||
1394 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
1395 | { | ||
1396 | GNUNET_SCHEDULER_cancel (end); | ||
1397 | end = GNUNET_SCHEDULER_NO_TASK; | ||
1398 | } | ||
1399 | if (GNUNET_SCHEDULER_NO_TASK != op_timeout) | ||
1400 | { | ||
1401 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
1402 | op_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
1403 | } | ||
1404 | ret = 0; | ||
1405 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | |||
1410 | static void | ||
1411 | resolve_peer_address (const struct GNUNET_PeerIdentity *id, | ||
1412 | const struct GNUNET_HELLO_Address *address, | ||
1413 | int numeric, | ||
1414 | enum GNUNET_TRANSPORT_PeerState state, | ||
1415 | struct GNUNET_TIME_Absolute state_timeout) | ||
1416 | { | ||
1417 | struct PeerResolutionContext *rc; | ||
1418 | |||
1419 | rc = GNUNET_new (struct PeerResolutionContext); | ||
1420 | GNUNET_assert(NULL != rc); | ||
1421 | GNUNET_CONTAINER_DLL_insert(rc_head, rc_tail, rc); | ||
1422 | address_resolutions++; | ||
1423 | |||
1424 | rc->id = (*id); | ||
1425 | rc->transport = GNUNET_strdup(address->transport_name); | ||
1426 | rc->addrcp = GNUNET_HELLO_address_copy (address); | ||
1427 | rc->printed = GNUNET_NO; | ||
1428 | rc->state = state; | ||
1429 | rc->state_timeout = state_timeout; | ||
1430 | /* Resolve address to string */ | ||
1431 | rc->asc = GNUNET_TRANSPORT_address_to_string (cfg, | ||
1432 | address, | ||
1433 | numeric, | ||
1434 | RESOLUTION_TIMEOUT, | ||
1435 | &process_peer_string, rc); | ||
1436 | } | ||
1437 | |||
1438 | |||
1439 | /** | ||
1440 | * Function called with information about a peers during a one shot iteration | ||
1441 | * | ||
1442 | * @param cls closure | ||
1443 | * @param peer identity of the peer, NULL for final callback when operation done | ||
1444 | * @param address binary address used to communicate with this peer, | ||
1445 | * NULL on disconnect or when done | ||
1446 | * @param state current state this peer is in | ||
1447 | * @param state_timeout time out for the current state | ||
1448 | */ | ||
1449 | static void | ||
1450 | process_peer_iteration_cb (void *cls, | ||
1451 | const struct GNUNET_PeerIdentity *peer, | ||
1452 | const struct GNUNET_HELLO_Address *address, | ||
1453 | enum GNUNET_TRANSPORT_PeerState state, | ||
1454 | struct GNUNET_TIME_Absolute state_timeout) | ||
1455 | { | ||
1456 | if (NULL == peer) | ||
1457 | { | ||
1458 | /* done */ | ||
1459 | address_resolution_in_progress = GNUNET_NO; | ||
1460 | pic = NULL; | ||
1461 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
1462 | GNUNET_SCHEDULER_cancel (end); | ||
1463 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
1464 | return; | ||
1465 | } | ||
1466 | |||
1467 | if ( (GNUNET_NO == iterate_all) && | ||
1468 | (GNUNET_NO == GNUNET_TRANSPORT_is_connected(state))) | ||
1469 | return; /* Display only connected peers */ | ||
1470 | |||
1471 | if (GNUNET_SCHEDULER_NO_TASK != op_timeout) | ||
1472 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
1473 | op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, | ||
1474 | &operation_timeout, | ||
1475 | NULL); | ||
1476 | |||
1477 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1478 | "Received address for peer `%s': %s\n", | ||
1479 | GNUNET_i2s (peer), | ||
1480 | address->transport_name); | ||
1481 | |||
1482 | if (NULL != address) | ||
1483 | resolve_peer_address (peer, address, numeric, state, state_timeout); | ||
1484 | else | ||
1485 | print_info (peer, NULL, NULL, state, state_timeout); | ||
1486 | } | ||
1487 | |||
1488 | |||
1489 | /** | ||
1490 | * Function called with information about a peers | ||
1491 | * | ||
1492 | * @param cls closure | ||
1493 | * @param peer identity of the peer, NULL for final callback when operation done | ||
1494 | * @param address binary address used to communicate with this peer, | ||
1495 | * NULL on disconnect or when done | ||
1496 | * @param state current state this peer is in | ||
1497 | * @param state_timeout time out for the current state | ||
1498 | * | ||
1499 | */ | ||
1500 | static void | ||
1501 | process_peer_monitoring_cb (void *cls, | ||
1502 | const struct GNUNET_PeerIdentity *peer, | ||
1503 | const struct GNUNET_HELLO_Address *address, | ||
1504 | enum GNUNET_TRANSPORT_PeerState state, | ||
1505 | struct GNUNET_TIME_Absolute state_timeout) | ||
1506 | { | ||
1507 | struct MonitoredPeer *m; | ||
1508 | |||
1509 | if (NULL == peer) | ||
1510 | { | ||
1511 | FPRINTF (stdout, | ||
1512 | "%s", | ||
1513 | _("Monitor disconnected from transport service. Reconnecting.\n")); | ||
1514 | return; | ||
1515 | } | ||
1516 | |||
1517 | if (GNUNET_SCHEDULER_NO_TASK != op_timeout) | ||
1518 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
1519 | op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, | ||
1520 | &operation_timeout, | ||
1521 | NULL); | ||
1522 | |||
1523 | if (NULL == (m = GNUNET_CONTAINER_multipeermap_get (monitored_peers, peer))) | ||
1524 | { | ||
1525 | m = GNUNET_new (struct MonitoredPeer); | ||
1526 | GNUNET_CONTAINER_multipeermap_put (monitored_peers, peer, | ||
1527 | m, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1528 | } | ||
1529 | else | ||
1530 | { | ||
1531 | if ( (m->state == state) && | ||
1532 | (m->state_timeout.abs_value_us == state_timeout.abs_value_us) && | ||
1533 | ((NULL == address) && (NULL == m->address))) | ||
1534 | { | ||
1535 | return; /* No real change */ | ||
1536 | } | ||
1537 | if ( (m->state == state) && ((NULL != address) && (NULL != m->address)) && | ||
1538 | (0 == GNUNET_HELLO_address_cmp(m->address, address))) | ||
1539 | return; /* No real change */ | ||
1540 | } | ||
1541 | |||
1542 | if (NULL != m->address) | ||
1543 | { | ||
1544 | GNUNET_free (m->address); | ||
1545 | m->address = NULL; | ||
1546 | } | ||
1547 | if (NULL != address) | ||
1548 | m->address = GNUNET_HELLO_address_copy (address); | ||
1549 | m->state = state; | ||
1550 | m->state_timeout = state_timeout; | ||
1551 | |||
1552 | if (NULL != address) | ||
1553 | resolve_peer_address (peer, | ||
1554 | m->address, | ||
1555 | numeric, | ||
1556 | m->state, | ||
1557 | m->state_timeout); | ||
1558 | else | ||
1559 | print_info (peer, | ||
1560 | NULL, | ||
1561 | NULL, | ||
1562 | m->state, | ||
1563 | m->state_timeout); | ||
1564 | } | ||
1565 | |||
1566 | |||
1567 | static void | ||
1568 | try_connect_cb (void *cls, | ||
1569 | const int result) | ||
1570 | { | ||
1571 | static int retries = 0; | ||
1572 | |||
1573 | if (GNUNET_OK == result) | ||
1574 | { | ||
1575 | tc_handle = NULL; | ||
1576 | return; | ||
1577 | } | ||
1578 | retries++; | ||
1579 | if (retries < 10) | ||
1580 | tc_handle = GNUNET_TRANSPORT_try_connect (handle, &pid, try_connect_cb, | ||
1581 | NULL); | ||
1582 | else | ||
1583 | { | ||
1584 | FPRINTF (stderr, | ||
1585 | "%s", | ||
1586 | _("Failed to send connect request to transport service\n")); | ||
1587 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
1588 | GNUNET_SCHEDULER_cancel (end); | ||
1589 | ret = 1; | ||
1590 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
1591 | return; | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1595 | |||
1596 | static void | ||
1597 | try_disconnect_cb (void *cls, | ||
1598 | const int result) | ||
1599 | { | ||
1600 | static int retries = 0; | ||
1601 | if (GNUNET_OK == result) | ||
1602 | { | ||
1603 | tc_handle = NULL; | ||
1604 | return; | ||
1605 | } | ||
1606 | retries++; | ||
1607 | if (retries < 10) | ||
1608 | tc_handle = GNUNET_TRANSPORT_try_disconnect (handle, &pid, try_disconnect_cb, | ||
1609 | NULL); | ||
1610 | else | ||
1611 | { | ||
1612 | FPRINTF (stderr, "%s", | ||
1613 | _("Failed to send connect request to transport service\n")); | ||
1614 | if (GNUNET_SCHEDULER_NO_TASK != end) | ||
1615 | GNUNET_SCHEDULER_cancel (end); | ||
1616 | ret = 1; | ||
1617 | end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
1618 | return; | ||
1619 | } | ||
1620 | } | ||
1621 | |||
1622 | |||
1623 | /** | ||
1624 | * Function called with the result of the check if the 'transport' | ||
1625 | * service is running. | ||
1626 | * | ||
1627 | * @param cls closure with our configuration | ||
1628 | * @param result #GNUNET_YES if transport is running | ||
1629 | */ | ||
1630 | static void | ||
1631 | testservice_task (void *cls, int result) | ||
1632 | { | ||
1633 | int counter = 0; | ||
1634 | ret = 1; | ||
1635 | |||
1636 | if (GNUNET_YES != result) | ||
1637 | { | ||
1638 | FPRINTF (stderr, _("Service `%s' is not running\n"), "transport"); | ||
1639 | return; | ||
1640 | } | ||
1641 | |||
1642 | if ((NULL != cpid) | ||
1643 | && (GNUNET_OK | ||
1644 | != GNUNET_CRYPTO_eddsa_public_key_from_string (cpid, strlen (cpid), | ||
1645 | &pid.public_key))) | ||
1646 | { | ||
1647 | FPRINTF (stderr, _("Failed to parse peer identity `%s'\n"), cpid); | ||
1648 | return; | ||
1649 | } | ||
1650 | |||
1651 | counter = benchmark_send + benchmark_receive + iterate_connections | ||
1652 | + monitor_connections + monitor_connects + try_connect + try_disconnect + | ||
1653 | + iterate_validation + monitor_validation; | ||
1654 | |||
1655 | if (1 < counter) | ||
1656 | { | ||
1657 | FPRINTF (stderr, | ||
1658 | _("Multiple operations given. Please choose only one operation: %s, %s, %s, %s, %s, %s\n"), | ||
1659 | "connect", "benchmark send", "benchmark receive", "information", | ||
1660 | "monitor", "events"); | ||
1661 | return; | ||
1662 | } | ||
1663 | if (0 == counter) | ||
1664 | { | ||
1665 | FPRINTF (stderr, | ||
1666 | _("No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s\n"), | ||
1667 | "connect", "benchmark send", "benchmark receive", "information", | ||
1668 | "monitor", "events"); | ||
1669 | return; | ||
1670 | } | ||
1671 | |||
1672 | if (try_connect) /* -C: Connect to peer */ | ||
1673 | { | ||
1674 | if (NULL == cpid) | ||
1675 | { | ||
1676 | FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"), | ||
1677 | "-C", "-p"); | ||
1678 | ret = 1; | ||
1679 | return; | ||
1680 | } | ||
1681 | handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, ¬ify_receive, | ||
1682 | ¬ify_connect, ¬ify_disconnect); | ||
1683 | if (NULL == handle) | ||
1684 | { | ||
1685 | FPRINTF (stderr, "%s", _("Failed to connect to transport service\n")); | ||
1686 | ret = 1; | ||
1687 | return; | ||
1688 | } | ||
1689 | tc_handle = GNUNET_TRANSPORT_try_connect (handle, &pid, try_connect_cb, | ||
1690 | NULL); | ||
1691 | if (NULL == tc_handle) | ||
1692 | { | ||
1693 | FPRINTF (stderr, "%s", | ||
1694 | _("Failed to send request to transport service\n")); | ||
1695 | ret = 1; | ||
1696 | return; | ||
1697 | } | ||
1698 | op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, | ||
1699 | NULL); | ||
1700 | |||
1701 | } | ||
1702 | else if (try_disconnect) /* -D: Disconnect from peer */ | ||
1703 | { | ||
1704 | if (NULL == cpid) | ||
1705 | { | ||
1706 | FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"), | ||
1707 | "-D", "-p"); | ||
1708 | ret = 1; | ||
1709 | return; | ||
1710 | } | ||
1711 | handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, ¬ify_receive, | ||
1712 | ¬ify_connect, ¬ify_disconnect); | ||
1713 | if (NULL == handle) | ||
1714 | { | ||
1715 | FPRINTF (stderr, "%s", _("Failed to connect to transport service\n")); | ||
1716 | ret = 1; | ||
1717 | return; | ||
1718 | } | ||
1719 | tc_handle = GNUNET_TRANSPORT_try_disconnect (handle, &pid, try_disconnect_cb, | ||
1720 | NULL); | ||
1721 | if (NULL == tc_handle) | ||
1722 | { | ||
1723 | FPRINTF (stderr, "%s", | ||
1724 | _("Failed to send request to transport service\n")); | ||
1725 | ret = 1; | ||
1726 | return; | ||
1727 | } | ||
1728 | op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, | ||
1729 | NULL); | ||
1730 | |||
1731 | } | ||
1732 | else if (benchmark_send) /* -s: Benchmark sending */ | ||
1733 | { | ||
1734 | if (NULL == cpid) | ||
1735 | { | ||
1736 | FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"), | ||
1737 | "-s", "-p"); | ||
1738 | ret = 1; | ||
1739 | return; | ||
1740 | } | ||
1741 | handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, ¬ify_receive, | ||
1742 | ¬ify_connect, ¬ify_disconnect); | ||
1743 | if (NULL == handle) | ||
1744 | { | ||
1745 | FPRINTF (stderr, "%s", _("Failed to connect to transport service\n")); | ||
1746 | ret = 1; | ||
1747 | return; | ||
1748 | } | ||
1749 | tc_handle = GNUNET_TRANSPORT_try_connect (handle, &pid, try_connect_cb, | ||
1750 | NULL); | ||
1751 | if (NULL == tc_handle) | ||
1752 | { | ||
1753 | FPRINTF (stderr, "%s", | ||
1754 | _("Failed to send request to transport service\n")); | ||
1755 | ret = 1; | ||
1756 | return; | ||
1757 | } | ||
1758 | start_time = GNUNET_TIME_absolute_get (); | ||
1759 | op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, | ||
1760 | NULL); | ||
1761 | } | ||
1762 | else if (benchmark_receive) /* -b: Benchmark receiving */ | ||
1763 | { | ||
1764 | handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, ¬ify_receive, NULL, | ||
1765 | NULL); | ||
1766 | if (NULL == handle) | ||
1767 | { | ||
1768 | FPRINTF (stderr, "%s", _("Failed to connect to transport service\n")); | ||
1769 | ret = 1; | ||
1770 | return; | ||
1771 | } | ||
1772 | if (verbosity > 0) | ||
1773 | FPRINTF (stdout, "%s", _("Starting to receive benchmark data\n")); | ||
1774 | start_time = GNUNET_TIME_absolute_get (); | ||
1775 | |||
1776 | } | ||
1777 | else if (iterate_connections) /* -i: List information about peers once */ | ||
1778 | { | ||
1779 | address_resolution_in_progress = GNUNET_YES; | ||
1780 | pic = GNUNET_TRANSPORT_monitor_peers (cfg, (NULL == cpid) ? NULL : &pid, | ||
1781 | GNUNET_YES, TIMEOUT, &process_peer_iteration_cb, (void *) cfg); | ||
1782 | op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, | ||
1783 | NULL); | ||
1784 | } | ||
1785 | else if (monitor_connections) /* -m: List information about peers continuously */ | ||
1786 | { | ||
1787 | monitored_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
1788 | address_resolution_in_progress = GNUNET_YES; | ||
1789 | pic = GNUNET_TRANSPORT_monitor_peers (cfg, (NULL == cpid) ? NULL : &pid, | ||
1790 | GNUNET_NO, TIMEOUT, | ||
1791 | &process_peer_monitoring_cb, (void *) cfg); | ||
1792 | } | ||
1793 | else if (iterate_validation) /* -d: Print information about validations */ | ||
1794 | { | ||
1795 | vic = GNUNET_TRANSPORT_monitor_validation_entries (cfg, | ||
1796 | (NULL == cpid) ? NULL : &pid, | ||
1797 | GNUNET_YES, TIMEOUT, | ||
1798 | &process_validation_cb, (void *) cfg); | ||
1799 | } | ||
1800 | else if (monitor_validation) /* -f: Print information about validations continuously */ | ||
1801 | { | ||
1802 | vic = GNUNET_TRANSPORT_monitor_validation_entries (cfg, | ||
1803 | (NULL == cpid) ? NULL : &pid, | ||
1804 | GNUNET_NO, TIMEOUT, | ||
1805 | &process_validation_cb, (void *) cfg); | ||
1806 | } | ||
1807 | else if (monitor_connects) /* -e : Monitor (dis)connect events continuously */ | ||
1808 | { | ||
1809 | monitor_connect_counter = 0; | ||
1810 | handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, NULL, | ||
1811 | &monitor_notify_connect, | ||
1812 | &monitor_notify_disconnect); | ||
1813 | if (NULL == handle) | ||
1814 | { | ||
1815 | FPRINTF (stderr, | ||
1816 | "%s", | ||
1817 | _("Failed to connect to transport service\n")); | ||
1818 | ret = 1; | ||
1819 | return; | ||
1820 | } | ||
1821 | ret = 0; | ||
1822 | } | ||
1823 | else | ||
1824 | { | ||
1825 | GNUNET_break(0); | ||
1826 | return; | ||
1827 | } | ||
1828 | |||
1829 | end = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
1830 | &shutdown_task, | ||
1831 | NULL); | ||
1832 | } | ||
1833 | |||
1834 | |||
1835 | /** | ||
1836 | * Main function that will be run by the scheduler. | ||
1837 | * | ||
1838 | * @param cls closure | ||
1839 | * @param args remaining command-line arguments | ||
1840 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
1841 | * @param mycfg configuration | ||
1842 | */ | ||
1843 | static void | ||
1844 | run (void *cls, | ||
1845 | char * const *args, | ||
1846 | const char *cfgfile, | ||
1847 | const struct GNUNET_CONFIGURATION_Handle *mycfg) | ||
1848 | { | ||
1849 | cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; | ||
1850 | if (test_configuration) | ||
1851 | { | ||
1852 | do_test_configuration (cfg); | ||
1853 | return; | ||
1854 | } | ||
1855 | GNUNET_CLIENT_service_test ("transport", cfg, GNUNET_TIME_UNIT_SECONDS, | ||
1856 | &testservice_task, (void *) cfg); | ||
1857 | } | ||
1858 | |||
1859 | int | ||
1860 | main (int argc, char * const *argv) | ||
1861 | { | ||
1862 | int res; | ||
1863 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1864 | { 'a', "all", NULL, | ||
1865 | gettext_noop ("print information for all peers (instead of only connected peers)"), | ||
1866 | 0, &GNUNET_GETOPT_set_one, &iterate_all }, | ||
1867 | { 'b', "benchmark", NULL, | ||
1868 | gettext_noop ("measure how fast we are receiving data from all peers (until CTRL-C)"), | ||
1869 | 0, &GNUNET_GETOPT_set_one, &benchmark_receive }, | ||
1870 | { 'C', "connect", | ||
1871 | NULL, gettext_noop ("connect to a peer"), 0, | ||
1872 | &GNUNET_GETOPT_set_one, &try_connect }, | ||
1873 | { 'D', "disconnect", | ||
1874 | NULL, gettext_noop ("disconnect to a peer"), 0, | ||
1875 | &GNUNET_GETOPT_set_one, &try_disconnect }, | ||
1876 | { 'd', "validation", NULL, | ||
1877 | gettext_noop ("print information for all pending validations "), | ||
1878 | 0, &GNUNET_GETOPT_set_one, &iterate_validation }, | ||
1879 | { 'f', "monitorvalidation", NULL, | ||
1880 | gettext_noop ("print information for all pending validations continously"), | ||
1881 | 0, &GNUNET_GETOPT_set_one, &monitor_validation }, | ||
1882 | { 'i', "information", NULL, | ||
1883 | gettext_noop ("provide information about all current connections (once)"), | ||
1884 | 0, &GNUNET_GETOPT_set_one, &iterate_connections }, | ||
1885 | { 'm', "monitor", NULL, | ||
1886 | gettext_noop ("provide information about all current connections (continuously)"), | ||
1887 | 0, &GNUNET_GETOPT_set_one, &monitor_connections }, | ||
1888 | { 'e', "events", NULL, | ||
1889 | gettext_noop ("provide information about all connects and disconnect events (continuously)"), | ||
1890 | 0, &GNUNET_GETOPT_set_one, &monitor_connects }, | ||
1891 | { 'n', "numeric", | ||
1892 | NULL, gettext_noop ("do not resolve hostnames"), 0, | ||
1893 | &GNUNET_GETOPT_set_one, &numeric }, | ||
1894 | { 'p', "peer", "PEER", | ||
1895 | gettext_noop ("peer identity"), 1, &GNUNET_GETOPT_set_string, | ||
1896 | &cpid }, | ||
1897 | { 's', "send", NULL, gettext_noop | ||
1898 | ("send data for benchmarking to the other peer (until CTRL-C)"), 0, | ||
1899 | &GNUNET_GETOPT_set_one, &benchmark_send }, | ||
1900 | { 't', "test", NULL, | ||
1901 | gettext_noop ("test transport configuration (involves external server)"), | ||
1902 | 0, &GNUNET_GETOPT_set_one, &test_configuration }, | ||
1903 | GNUNET_GETOPT_OPTION_VERBOSE (&verbosity), | ||
1904 | GNUNET_GETOPT_OPTION_END | ||
1905 | }; | ||
1906 | |||
1907 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
1908 | return 2; | ||
1909 | |||
1910 | res = GNUNET_PROGRAM_run (argc, argv, | ||
1911 | "gnunet-transport", | ||
1912 | gettext_noop ("Direct access to transport service."), | ||
1913 | options, | ||
1914 | &run, NULL); | ||
1915 | GNUNET_free((void *) argv); | ||
1916 | if (GNUNET_OK == res) | ||
1917 | return ret; | ||
1918 | return 1; | ||
1919 | } | ||
1920 | |||
1921 | /* end of gnunet-transport.c */ | ||