aboutsummaryrefslogtreecommitdiff
path: root/src/integration-tests
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2012-04-04 14:18:43 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2012-04-04 14:18:43 +0000
commit6e86ae790d66d9f6f5c93d16d1b2367b8364d554 (patch)
tree839623769e6767de75fa6efbabc66723c32d9f7d /src/integration-tests
parentda438f75b99ca61be3dbc7a9b0726a229711024a (diff)
downloadgnunet-6e86ae790d66d9f6f5c93d16d1b2367b8364d554.tar.gz
gnunet-6e86ae790d66d9f6f5c93d16d1b2367b8364d554.zip
- connection_watchdog tool
Diffstat (limited to 'src/integration-tests')
-rw-r--r--src/integration-tests/Makefile.am12
-rw-r--r--src/integration-tests/connection_watchdog.c376
2 files changed, 387 insertions, 1 deletions
diff --git a/src/integration-tests/Makefile.am b/src/integration-tests/Makefile.am
index 8adbf2bcd..31f82170b 100644
--- a/src/integration-tests/Makefile.am
+++ b/src/integration-tests/Makefile.am
@@ -9,10 +9,13 @@ if USE_COVERAGE
9 XLIB = -lgcov 9 XLIB = -lgcov
10endif 10endif
11 11
12bin_PROGRAMS = 12#bin_PROGRAMS = \
13# connection_watchdog
13 14
14check_PROGRAMS = 15check_PROGRAMS =
15 16
17noinst_PROGRAMS = connection_watchdog
18
16noinst_SCRIPTS = \ 19noinst_SCRIPTS = \
17 gnunet_testing.py \ 20 gnunet_testing.py \
18 gnunet_pyexpect.py \ 21 gnunet_pyexpect.py \
@@ -38,6 +41,13 @@ TESTS = \
38 $(check_SCRIPTS) 41 $(check_SCRIPTS)
39endif 42endif
40 43
44connection_watchdog_SOURCE = \
45 connection_watchdog.c
46connection_watchdog_LDADD = \
47 $(top_builddir)/src/core/libgnunetcore.la \
48 $(top_builddir)/src/transport/libgnunettransport.la \
49 $(top_builddir)/src/util/libgnunetutil.la
50
41do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' 51do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g'
42 52
43%.py: %.py.in Makefile 53%.py: %.py.in Makefile
diff --git a/src/integration-tests/connection_watchdog.c b/src/integration-tests/connection_watchdog.c
new file mode 100644
index 000000000..f83cfccda
--- /dev/null
+++ b/src/integration-tests/connection_watchdog.c
@@ -0,0 +1,376 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009, 2010 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 * @file integration-test/connection_watchdog.c
22 * @brief tool to monitor core and transport connections for consistency
23 * @author Matthias Wachs
24 */
25#include "platform.h"
26#include "gnunet_common.h"
27#include "gnunet_constants.h"
28#include "gnunet_arm_service.h"
29#include "gnunet_core_service.h"
30#include "gnunet_getopt_lib.h"
31#include "gnunet_os_lib.h"
32#include "gnunet_program_lib.h"
33#include "gnunet_scheduler_lib.h"
34#include "gnunet_transport_service.h"
35#include "gnunet_statistics_service.h"
36
37/**
38 * Final status code.
39 */
40static int ret;
41
42struct GNUNET_TRANSPORT_Handle *th;
43struct GNUNET_CORE_Handle *ch;
44struct GNUNET_PeerIdentity my_peer_id;
45
46static unsigned int transport_connections;
47static unsigned int core_connections;
48
49
50
51static struct GNUNET_CONTAINER_MultiHashMap *peers;
52
53struct PeerContainer
54{
55 struct GNUNET_PeerIdentity id;
56 int transport_connected;
57 int core_connected;
58};
59
60
61int map_check_it (void *cls,
62 const GNUNET_HashCode * key,
63 void *value)
64{
65 struct PeerContainer *pc = value;
66 if (pc->core_connected != pc->transport_connected)
67 {
68 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
69 "Inconsistend peer `%s': TRANSPORT %s <-> CORE %s\n",
70 GNUNET_i2s (&pc->id),
71 (GNUNET_YES == pc->transport_connected) ? "YES" : "NO",
72 (GNUNET_YES == pc->core_connected) ? "YES" : "NO");
73 }
74
75 return GNUNET_OK;
76}
77
78
79int map_cleanup_it (void *cls,
80 const GNUNET_HashCode * key,
81 void *value)
82{
83 struct PeerContainer *pc = value;
84 GNUNET_CONTAINER_multihashmap_remove(peers, key, value);
85 GNUNET_free (pc);
86 return GNUNET_OK;
87}
88
89static void map_check (void)
90{
91
92 GNUNET_CONTAINER_multihashmap_iterate (peers, &map_check_it, NULL);
93}
94
95static void
96map_connect (const struct GNUNET_PeerIdentity *peer, void * source)
97{
98 struct PeerContainer * pc;
99 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(peers, &peer->hashPubKey))
100 {
101 pc = GNUNET_malloc (sizeof (struct PeerContainer));
102 pc->id = *peer;
103 pc->core_connected = GNUNET_NO;
104 pc->transport_connected = GNUNET_NO;
105 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(peers, &peer->hashPubKey, pc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
106 }
107
108 pc = GNUNET_CONTAINER_multihashmap_get(peers, &peer->hashPubKey);
109 if (source == th)
110 {
111 if (GNUNET_NO == pc->transport_connected)
112 {
113 pc->transport_connected = GNUNET_YES;
114 return;
115 }
116 else
117 {
118 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
119 "%s notified multiple times about for peers `%s' (%s : %s)\n",
120 "TRANSPORT",
121 GNUNET_i2s (&pc->id),
122 "CORE", (pc->core_connected == GNUNET_YES) ? "yes" : "no");
123 GNUNET_break (0);
124 }
125 }
126 if (source == ch)
127 {
128 if (GNUNET_NO == pc->core_connected)
129 {
130 pc->core_connected = GNUNET_YES;
131 return;
132 }
133 else
134 {
135 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
136 "%s notified multiple times about for peers `%s' (%s : %s)\n",
137 "CORE",
138 GNUNET_i2s (&pc->id),
139 "TRANSPORT", (pc->transport_connected == GNUNET_YES) ? "yes" : "no");
140 GNUNET_break (0);
141 return;
142 }
143 }
144}
145
146
147static void
148map_disconnect (const struct GNUNET_PeerIdentity * peer, void * source)
149{
150
151 struct PeerContainer * pc;
152 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(peers, &peer->hashPubKey))
153 {
154 if (source == th)
155 {
156 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
157 "%s disconnect notification for unknown peer `%s'\n",
158 "TRANSPORT", GNUNET_i2s (peer));
159 GNUNET_break (0);
160 return;
161 }
162 if (source == ch)
163 {
164 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
165 "%s disconnect notification for unknown peer `%s'\n",
166 "CORE", GNUNET_i2s (peer));
167 return;
168 }
169 }
170
171 pc = GNUNET_CONTAINER_multihashmap_get(peers, &peer->hashPubKey);
172 if (source == th)
173 {
174 if (GNUNET_YES == pc->transport_connected)
175 {
176 pc->transport_connected = GNUNET_NO;
177 }
178 else
179 {
180 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
181 "%s notified for not connected peer `%s' (%s : %s)\n",
182 "TRANSPORT",
183 GNUNET_i2s (&pc->id),
184 "CORE", (pc->core_connected == GNUNET_YES) ? "yes" : "no");
185 GNUNET_break (0);
186 }
187 }
188 if (source == ch)
189 {
190 if (GNUNET_YES == pc->core_connected)
191 {
192 pc->core_connected = GNUNET_NO;
193 }
194 else
195 {
196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
197 "%s notified for not connected peer `%s' (%s : %s)\n",
198 "CORE",
199 GNUNET_i2s (&pc->id),
200 "TRANSPORT", (pc->transport_connected == GNUNET_YES) ? "yes" : "no");
201 GNUNET_break (0);
202 }
203 }
204
205 if ((GNUNET_NO == pc->core_connected) && (GNUNET_NO == pc->transport_connected))
206 {
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing peer `%s'\n", GNUNET_i2s (&pc->id));
208 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (peers, &peer->hashPubKey, pc));
209 GNUNET_free (pc);
210 }
211
212}
213
214
215static void
216cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
217{
218 if (NULL != th)
219 {
220 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disconnecting from transport service\n");
221 GNUNET_TRANSPORT_disconnect (th);
222 th = NULL;
223 }
224 if (NULL != ch)
225 {
226 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disconnecting from core service\n");
227 GNUNET_CORE_disconnect (ch);
228 ch = NULL;
229 }
230
231 map_check();
232
233 GNUNET_CONTAINER_multihashmap_iterate (peers, &map_cleanup_it, NULL);
234 GNUNET_CONTAINER_multihashmap_destroy(peers);
235}
236
237void
238transport_notify_connect_cb (void *cls,
239 const struct GNUNET_PeerIdentity
240 * peer,
241 const struct
242 GNUNET_ATS_Information * ats,
243 uint32_t ats_count)
244{
245 transport_connections ++;
246 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "TRANSPORT connect notification for peer `%s' (%u total)\n",
247 GNUNET_i2s (peer), transport_connections);
248 map_connect (peer, th);
249}
250
251/**
252 * Function called to notify transport users that another
253 * peer disconnected from us.
254 *
255 * @param cls closure
256 * @param peer the peer that disconnected
257 */
258void
259transport_notify_disconnect_cb (void *cls,
260 const struct
261 GNUNET_PeerIdentity * peer)
262{
263 GNUNET_assert (transport_connections > 0);
264 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "TRANSPORT disconnect notification for peer `%s' (%u total)\n",
265 GNUNET_i2s (peer), transport_connections) ;
266 map_disconnect (peer, th);
267 transport_connections --;
268
269}
270
271
272static void
273core_connect_cb (void *cls, const struct GNUNET_PeerIdentity *peer,
274 const struct GNUNET_ATS_Information *atsi,
275 unsigned int atsi_count)
276{
277 if (0 != memcmp (peer, &my_peer_id, sizeof (struct GNUNET_PeerIdentity)))
278 {
279 core_connections ++;
280 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CORE connect notification for peer `%s' (%u total)\n",
281 GNUNET_i2s (peer), core_connections);
282 map_connect (peer, ch);
283 }
284 else
285 {
286 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CORE connect notification for myself `%s' (%u total)\n",
287 GNUNET_i2s (peer), core_connections);
288 }
289}
290
291static void
292core_disconnect_cb (void *cls,
293 const struct
294 GNUNET_PeerIdentity * peer)
295{
296 if (0 != memcmp (peer, &my_peer_id, sizeof (struct GNUNET_PeerIdentity)))
297 {
298 GNUNET_assert (core_connections >= 0);
299 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CORE disconnect notification for peer `%s' (%u total)\n",
300 GNUNET_i2s (peer), core_connections);
301 map_disconnect (peer, ch);
302 core_connections --;
303 }
304 else
305 {
306 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CORE disconnect notification for myself `%s' (%u total)\n",
307 GNUNET_i2s (peer), core_connections);
308 }
309
310}
311
312static void
313core_init_cb (void *cls, struct GNUNET_CORE_Handle *server,
314 const struct GNUNET_PeerIdentity *my_identity)
315{
316 my_peer_id = *my_identity;
317 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connected to core service\n");
318}
319
320/**
321 * Main function that will be run by the scheduler.
322 *
323 * @param cls closure
324 * @param args remaining command-line arguments
325 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
326 * @param cfg configuration
327 */
328static void
329run (void *cls, char *const *args, const char *cfgfile,
330 const struct GNUNET_CONFIGURATION_Handle *cfg)
331{
332 transport_connections = 0;
333 core_connections = 0;
334
335 peers = GNUNET_CONTAINER_multihashmap_create (20);
336
337 th = GNUNET_TRANSPORT_connect(cfg, NULL, NULL, NULL,
338 &transport_notify_connect_cb,
339 &transport_notify_disconnect_cb);
340 GNUNET_assert (th != NULL);
341 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connected to transport service\n");
342 ch = GNUNET_CORE_connect (cfg, 1, NULL,
343 &core_init_cb,
344 &core_connect_cb,
345 &core_disconnect_cb,
346 NULL, GNUNET_NO,
347 NULL, GNUNET_NO,
348 NULL);
349 GNUNET_assert (ch != NULL);
350
351 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, NULL);
352
353}
354
355
356/**
357 * The main function.
358 *
359 * @param argc number of arguments from the command line
360 * @param argv command line arguments
361 * @return 0 ok, 1 on error
362 */
363int
364main (int argc, char *const *argv)
365{
366 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
367 /* FIMXE: add options here */
368 GNUNET_GETOPT_OPTION_END
369 };
370 return (GNUNET_OK ==
371 GNUNET_PROGRAM_run (argc, argv, "gnunet-template",
372 gettext_noop ("help text"), options, &run,
373 NULL)) ? ret : 1;
374}
375
376/* end of connection_watchdog.c */