aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-03-18 10:36:29 +0000
committerChristian Grothoff <christian@grothoff.org>2013-03-18 10:36:29 +0000
commitae98f60033937c8c94a015cb82dcf1393298a759 (patch)
treeaab88ff7b22550dc13ab9b56f967460f1c022c21
parent7ad3063679f5976245b151e5c62efad04eada06c (diff)
downloadgnunet-ae98f60033937c8c94a015cb82dcf1393298a759.tar.gz
gnunet-ae98f60033937c8c94a015cb82dcf1393298a759.zip
-enable DV status monitoring
-rw-r--r--src/dv/Makefile.am10
-rw-r--r--src/dv/gnunet-dv.c184
-rw-r--r--src/dv/gnunet-service-dv.c183
3 files changed, 249 insertions, 128 deletions
diff --git a/src/dv/Makefile.am b/src/dv/Makefile.am
index 3c3998535..919f49e69 100644
--- a/src/dv/Makefile.am
+++ b/src/dv/Makefile.am
@@ -32,6 +32,9 @@ libgnunetdv_la_LDFLAGS = \
32 -version-info 0:0:0 32 -version-info 0:0:0
33 33
34 34
35noinst_PROGRAMS = \
36 gnunet-dv
37
35libexec_PROGRAMS = \ 38libexec_PROGRAMS = \
36 gnunet-service-dv 39 gnunet-service-dv
37 40
@@ -44,6 +47,13 @@ gnunet_service_dv_LDADD = \
44 $(top_builddir)/src/util/libgnunetutil.la \ 47 $(top_builddir)/src/util/libgnunetutil.la \
45 $(GN_LIBINTL) 48 $(GN_LIBINTL)
46 49
50gnunet_dv_SOURCES = \
51 gnunet-dv.c dv.h
52gnunet_dv_LDADD = \
53 libgnunetdv.la \
54 $(top_builddir)/src/util/libgnunetutil.la \
55 $(GN_LIBINTL)
56
47libgnunet_plugin_transport_dv_la_SOURCES = \ 57libgnunet_plugin_transport_dv_la_SOURCES = \
48 plugin_transport_dv.c 58 plugin_transport_dv.c
49libgnunet_plugin_transport_dv_la_LIBADD = \ 59libgnunet_plugin_transport_dv_la_LIBADD = \
diff --git a/src/dv/gnunet-dv.c b/src/dv/gnunet-dv.c
new file mode 100644
index 000000000..77324978e
--- /dev/null
+++ b/src/dv/gnunet-dv.c
@@ -0,0 +1,184 @@
1/*
2 This file is part of GNUnet.
3 (C) 2013 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 dv/gnunet-dv.c
22 * @brief DV monitoring command line tool
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_dv_service.h"
28
29/**
30 * Handle to DV service.
31 */
32static struct GNUNET_DV_ServiceHandle *sh;
33
34/**
35 * Was verbose specified?
36 */
37static int verbose;
38
39
40/**
41 * Function called if DV starts to be able to talk to a peer.
42 *
43 * @param cls closure
44 * @param peer newly connected peer
45 * @param distance distance to the peer
46 */
47static void
48connect_cb (void *cls,
49 const struct GNUNET_PeerIdentity *peer,
50 uint32_t distance)
51{
52 fprintf (stderr, "Connect: %s at %u\n",
53 GNUNET_i2s (peer),
54 (unsigned int) distance);
55}
56
57
58/**
59 * Function called if DV distance to a peer is changed.
60 *
61 * @param cls closure
62 * @param peer connected peer
63 * @param distance new distance to the peer
64 */
65static void
66change_cb (void *cls,
67 const struct GNUNET_PeerIdentity *peer,
68 uint32_t distance)
69{
70 fprintf (stderr, "Change: %s at %u\n",
71 GNUNET_i2s (peer),
72 (unsigned int) distance);
73}
74
75
76/**
77 * Function called if DV is no longer able to talk to a peer.
78 *
79 * @param cls closure
80 * @param peer peer that disconnected
81 */
82static void
83disconnect_cb (void *cls,
84 const struct GNUNET_PeerIdentity *peer)
85{
86 fprintf (stderr, "Disconnect: %s\n",
87 GNUNET_i2s (peer));
88}
89
90
91/**
92 * Function called if DV receives a message for this peer.
93 *
94 * @param cls closure
95 * @param sender sender of the message
96 * @param distance how far did the message travel
97 * @param msg actual message payload
98 */
99static void
100message_cb (void *cls,
101 const struct GNUNET_PeerIdentity *sender,
102 uint32_t distance,
103 const struct GNUNET_MessageHeader *msg)
104{
105 if (verbose)
106 fprintf (stderr, "Message: %s at %u sends %u bytes of type %u\n",
107 GNUNET_i2s (sender),
108 (unsigned int) distance,
109 (unsigned int) ntohs (msg->size),
110 (unsigned int) ntohs (msg->type));
111}
112
113
114/**
115 * Task run on shutdown.
116 *
117 * @param cls NULL
118 * @param tc unused
119 */
120static void
121shutdown_task (void *cls,
122 const struct GNUNET_SCHEDULER_TaskContext *tc)
123{
124 GNUNET_DV_service_disconnect (sh);
125 sh = NULL;
126}
127
128
129/**
130 * Main function that will be run by the scheduler.
131 *
132 * @param cls closure
133 * @param args remaining command-line arguments
134 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
135 * @param cfg configuration
136 */
137static void
138run (void *cls, char *const *args, const char *cfgfile,
139 const struct GNUNET_CONFIGURATION_Handle *cfg)
140{
141 sh = GNUNET_DV_service_connect (cfg, NULL,
142 &connect_cb,
143 &change_cb,
144 &disconnect_cb,
145 &message_cb);
146 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
147 &shutdown_task, NULL);
148}
149
150
151/**
152 * The main function.
153 *
154 * @param argc number of arguments from the command line
155 * @param argv command line arguments
156 * @return 0 ok, 1 on error
157 */
158int
159main (int argc, char *const *argv)
160{
161 int res;
162
163 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
164 {'V', "verbose", NULL,
165 gettext_noop ("verbose output"),
166 0, &GNUNET_GETOPT_set_one, &verbose},
167 GNUNET_GETOPT_OPTION_END
168 };
169
170 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
171 return 2;
172
173 res = GNUNET_PROGRAM_run (argc, argv, "gnunet-dv",
174 gettext_noop ("Print information about DV state"),
175 options, &run,
176 NULL);
177 GNUNET_free ((void *) argv);
178
179 if (GNUNET_OK != res)
180 return 1;
181 return 0;
182}
183
184/* end of gnunet-dv.c */
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c
index 23fff3f3b..edb06c43d 100644
--- a/src/dv/gnunet-service-dv.c
+++ b/src/dv/gnunet-service-dv.c
@@ -52,6 +52,11 @@
52#define MAX_QUEUE_SIZE 16 52#define MAX_QUEUE_SIZE 16
53 53
54/** 54/**
55 * Maximum number of messages we queue towards the clients/plugin.
56 */
57#define MAX_QUEUE_SIZE_PLUGIN 1024
58
59/**
55 * The default fisheye depth, from how many hops away will 60 * The default fisheye depth, from how many hops away will
56 * we keep peers? 61 * we keep peers?
57 */ 62 */
@@ -317,26 +322,11 @@ static struct GNUNET_PeerIdentity my_identity;
317static const struct GNUNET_CONFIGURATION_Handle *cfg; 322static const struct GNUNET_CONFIGURATION_Handle *cfg;
318 323
319/** 324/**
320 * The client, the DV plugin connected to us. Hopefully 325 * The client, the DV plugin connected to us (or an event monitor).
321 * this client will never change, although if the plugin dies 326 * Hopefully this client will never change, although if the plugin
322 * and returns for some reason it may happen. 327 * dies and returns for some reason it may happen.
323 */
324static struct GNUNET_SERVER_Client *client_handle;
325
326/**
327 * Transmit handle to the plugin.
328 */ 328 */
329static struct GNUNET_SERVER_TransmitHandle *plugin_transmit_handle; 329static struct GNUNET_SERVER_NotificationContext *nc;
330
331/**
332 * Head of DLL for client messages
333 */
334static struct PendingMessage *plugin_pending_head;
335
336/**
337 * Tail of DLL for client messages
338 */
339static struct PendingMessage *plugin_pending_tail;
340 330
341/** 331/**
342 * Handle for the statistics service. 332 * Handle for the statistics service.
@@ -366,51 +356,6 @@ get_atsi_distance (const struct GNUNET_ATS_Information *atsi,
366 356
367 357
368/** 358/**
369 * Function called to notify a client about the socket
370 * begin ready to queue more data. "buf" will be
371 * NULL and "size" zero if the socket was closed for
372 * writing in the meantime.
373 *
374 * @param cls closure
375 * @param size number of bytes available in buf
376 * @param buf where the callee should write the message
377 * @return number of bytes written to buf
378 */
379static size_t
380transmit_to_plugin (void *cls, size_t size, void *buf)
381{
382 char *cbuf = buf;
383 struct PendingMessage *reply;
384 size_t off;
385 size_t msize;
386
387 plugin_transmit_handle = NULL;
388 if (NULL == buf)
389 {
390 /* client disconnected */
391 return 0;
392 }
393 off = 0;
394 while ( (NULL != (reply = plugin_pending_head)) &&
395 (size >= off + (msize = ntohs (reply->msg->size))))
396 {
397 GNUNET_CONTAINER_DLL_remove (plugin_pending_head, plugin_pending_tail,
398 reply);
399 memcpy (&cbuf[off], reply->msg, msize);
400 GNUNET_free (reply);
401 off += msize;
402 }
403 if (NULL != plugin_pending_head)
404 plugin_transmit_handle =
405 GNUNET_SERVER_notify_transmit_ready (client_handle,
406 msize,
407 GNUNET_TIME_UNIT_FOREVER_REL,
408 &transmit_to_plugin, NULL);
409 return off;
410}
411
412
413/**
414 * Forward a message from another peer to the plugin. 359 * Forward a message from another peer to the plugin.
415 * 360 *
416 * @param message the message to send to the plugin 361 * @param message the message to send to the plugin
@@ -423,18 +368,8 @@ send_data_to_plugin (const struct GNUNET_MessageHeader *message,
423 uint32_t distance) 368 uint32_t distance)
424{ 369{
425 struct GNUNET_DV_ReceivedMessage *received_msg; 370 struct GNUNET_DV_ReceivedMessage *received_msg;
426 struct PendingMessage *pending_message;
427 size_t size; 371 size_t size;
428 372
429 if (NULL == client_handle)
430 {
431 GNUNET_STATISTICS_update (stats,
432 "# messages discarded (no plugin)",
433 1, GNUNET_NO);
434 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
435 _("Refusing to queue messages, DV plugin not active.\n"));
436 return;
437 }
438 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 373 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
439 "Delivering message from peer `%s'\n", 374 "Delivering message from peer `%s'\n",
440 GNUNET_i2s (origin)); 375 GNUNET_i2s (origin));
@@ -445,21 +380,16 @@ send_data_to_plugin (const struct GNUNET_MessageHeader *message,
445 GNUNET_break (0); /* too big */ 380 GNUNET_break (0); /* too big */
446 return; 381 return;
447 } 382 }
448 pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + size); 383 received_msg = GNUNET_malloc (size);
449 received_msg = (struct GNUNET_DV_ReceivedMessage *) &pending_message[1];
450 received_msg->header.size = htons (size); 384 received_msg->header.size = htons (size);
451 received_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DV_RECV); 385 received_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DV_RECV);
452 received_msg->distance = htonl (distance); 386 received_msg->distance = htonl (distance);
453 received_msg->sender = *origin; 387 received_msg->sender = *origin;
454 memcpy (&received_msg[1], message, ntohs (message->size)); 388 memcpy (&received_msg[1], message, ntohs (message->size));
455 GNUNET_CONTAINER_DLL_insert_tail (plugin_pending_head, 389 GNUNET_SERVER_notification_context_broadcast (nc,
456 plugin_pending_tail, 390 &received_msg->header,
457 pending_message); 391 GNUNET_YES);
458 if (NULL == plugin_transmit_handle) 392 GNUNET_free (received_msg);
459 plugin_transmit_handle =
460 GNUNET_SERVER_notify_transmit_ready (client_handle, size,
461 GNUNET_TIME_UNIT_FOREVER_REL,
462 &transmit_to_plugin, NULL);
463} 393}
464 394
465 395
@@ -473,29 +403,9 @@ send_data_to_plugin (const struct GNUNET_MessageHeader *message,
473static void 403static void
474send_control_to_plugin (const struct GNUNET_MessageHeader *message) 404send_control_to_plugin (const struct GNUNET_MessageHeader *message)
475{ 405{
476 struct PendingMessage *pending_message; 406 GNUNET_SERVER_notification_context_broadcast (nc,
477 size_t size; 407 message,
478 408 GNUNET_NO);
479 if (NULL == client_handle)
480 {
481 GNUNET_STATISTICS_update (stats,
482 "# control messages discarded (no plugin)",
483 1, GNUNET_NO);
484 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
485 _("Refusing to queue messages, DV plugin not active.\n"));
486 return;
487 }
488 size = ntohs (message->size);
489 pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + size);
490 memcpy (&pending_message[1], message, size);
491 GNUNET_CONTAINER_DLL_insert_tail (plugin_pending_head,
492 plugin_pending_tail,
493 pending_message);
494 if (NULL == plugin_transmit_handle)
495 plugin_transmit_handle =
496 GNUNET_SERVER_notify_transmit_ready (client_handle, size,
497 GNUNET_TIME_UNIT_FOREVER_REL,
498 &transmit_to_plugin, NULL);
499} 409}
500 410
501 411
@@ -561,8 +471,6 @@ send_connect_to_plugin (const struct GNUNET_PeerIdentity *target,
561{ 471{
562 struct GNUNET_DV_ConnectMessage cm; 472 struct GNUNET_DV_ConnectMessage cm;
563 473
564 if (NULL == client_handle)
565 return;
566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
567 "Delivering CONNECT about peer `%s'\n", 475 "Delivering CONNECT about peer `%s'\n",
568 GNUNET_i2s (target)); 476 GNUNET_i2s (target));
@@ -584,8 +492,6 @@ send_disconnect_to_plugin (const struct GNUNET_PeerIdentity *target)
584{ 492{
585 struct GNUNET_DV_DisconnectMessage dm; 493 struct GNUNET_DV_DisconnectMessage dm;
586 494
587 if (NULL == client_handle)
588 return;
589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 495 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
590 "Delivering DISCONNECT about peer `%s'\n", 496 "Delivering DISCONNECT about peer `%s'\n",
591 GNUNET_i2s (target)); 497 GNUNET_i2s (target));
@@ -1535,7 +1441,6 @@ free_direct_neighbors (void *cls, const struct GNUNET_HashCode * key, void *valu
1535static void 1441static void
1536shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1442shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1537{ 1443{
1538 struct PendingMessage *pending;
1539 unsigned int i; 1444 unsigned int i;
1540 1445
1541 GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, 1446 GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors,
@@ -1548,13 +1453,8 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1548 core_api = NULL; 1453 core_api = NULL;
1549 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 1454 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
1550 stats = NULL; 1455 stats = NULL;
1551 while (NULL != (pending = plugin_pending_head)) 1456 GNUNET_SERVER_notification_context_destroy (nc);
1552 { 1457 nc = NULL;
1553 GNUNET_CONTAINER_DLL_remove (plugin_pending_head,
1554 plugin_pending_tail,
1555 pending);
1556 GNUNET_free (pending);
1557 }
1558 for (i=0;i<DEFAULT_FISHEYE_DEPTH - 1;i++) 1458 for (i=0;i<DEFAULT_FISHEYE_DEPTH - 1;i++)
1559 GNUNET_array_grow (consensi[i].targets, 1459 GNUNET_array_grow (consensi[i].targets,
1560 consensi[i].array_length, 1460 consensi[i].array_length,
@@ -1563,6 +1463,36 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1563 1463
1564 1464
1565/** 1465/**
1466 * Notify newly connected client about an existing route.
1467 *
1468 * @param cls the 'struct GNUNET_SERVER_Client'
1469 * @param key peer identity
1470 * @param value the XXX.
1471 * @return GNUNET_OK (continue to iterate)
1472 */
1473static int
1474add_route (void *cls,
1475 const struct GNUNET_HashCode *key,
1476 void *value)
1477{
1478 struct GNUNET_SERVER_Client *client = cls;
1479 struct Route *route = value;
1480 struct GNUNET_DV_ConnectMessage cm;
1481
1482 cm.header.size = htons (sizeof (cm));
1483 cm.header.type = htons (GNUNET_MESSAGE_TYPE_DV_CONNECT);
1484 cm.distance = htonl (route->target.distance);
1485 cm.peer = route->target.peer;
1486
1487 GNUNET_SERVER_notification_context_unicast (nc,
1488 client,
1489 &cm.header,
1490 GNUNET_NO);
1491 return GNUNET_OK;
1492}
1493
1494
1495/**
1566 * Handle START-message. This is the first message sent to us 1496 * Handle START-message. This is the first message sent to us
1567 * by the client (can only be one!). 1497 * by the client (can only be one!).
1568 * 1498 *
@@ -1574,15 +1504,10 @@ static void
1574handle_start (void *cls, struct GNUNET_SERVER_Client *client, 1504handle_start (void *cls, struct GNUNET_SERVER_Client *client,
1575 const struct GNUNET_MessageHeader *message) 1505 const struct GNUNET_MessageHeader *message)
1576{ 1506{
1577 if (NULL != client_handle) 1507 GNUNET_SERVER_notification_context_add (nc, client);
1578 { 1508 GNUNET_CONTAINER_multihashmap_iterate (all_routes,
1579 /* forcefully drop old client */ 1509 &add_route,
1580 GNUNET_SERVER_client_disconnect (client_handle); 1510 client);
1581 GNUNET_SERVER_client_drop (client_handle);
1582 }
1583 client_handle = client;
1584 GNUNET_SERVER_client_keep (client_handle);
1585 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1586} 1511}
1587 1512
1588 1513
@@ -1642,6 +1567,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1642 1567
1643 if (NULL == core_api) 1568 if (NULL == core_api)
1644 return; 1569 return;
1570 nc = GNUNET_SERVER_notification_context_create (server,
1571 MAX_QUEUE_SIZE_PLUGIN);
1645 stats = GNUNET_STATISTICS_create ("dv", cfg); 1572 stats = GNUNET_STATISTICS_create ("dv", cfg);
1646 GNUNET_SERVER_add_handlers (server, plugin_handlers); 1573 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1647 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 1574 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,