aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-07-07 06:27:10 +0000
committerChristian Grothoff <christian@grothoff.org>2010-07-07 06:27:10 +0000
commitac2de52a5de68f6f4f13b7aa01a481869fffc6aa (patch)
tree856c9f0b2f55f8cae99f3c7b3bf22beaecbf58da /src
parentc1a3c11f8665432d9db6d549c28c0329668e66af (diff)
downloadgnunet-ac2de52a5de68f6f4f13b7aa01a481869fffc6aa.tar.gz
gnunet-ac2de52a5de68f6f4f13b7aa01a481869fffc6aa.zip
hacks from trip
Diffstat (limited to 'src')
-rw-r--r--src/core/core.h58
-rw-r--r--src/core/core_api.c32
-rw-r--r--src/core/gnunet-service-core.c84
-rw-r--r--src/core/test_core_api.c2
-rw-r--r--src/core/test_core_api_reliability.c2
-rw-r--r--src/core/test_core_api_start_only.c2
-rw-r--r--src/dht/gnunet-service-dht.c1
-rw-r--r--src/dv/gnunet-service-dv.c6
-rw-r--r--src/dv/test_transport_api_dv.c20
-rw-r--r--src/fs/gnunet-service-fs.c175
-rw-r--r--src/hostlist/gnunet-daemon-hostlist.c2
-rw-r--r--src/hostlist/hostlist-server.c8
-rw-r--r--src/hostlist/test_gnunet_daemon_hostlist_learning.c14
-rw-r--r--src/include/gnunet_core_service.h22
-rw-r--r--src/include/gnunet_peerinfo_service.h13
-rw-r--r--src/include/gnunet_protocols.h70
-rw-r--r--src/include/gnunet_statistics_service.h22
-rw-r--r--src/peerinfo-tool/gnunet-peerinfo.c49
-rwxr-xr-xsrc/peerinfo-tool/test_gnunet_peerinfo.py.in12
-rw-r--r--src/peerinfo/gnunet-service-peerinfo.c181
-rw-r--r--src/peerinfo/peerinfo.h37
-rw-r--r--src/peerinfo/peerinfo_api.c40
-rw-r--r--src/peerinfo/peerinfo_api_notify.c2
-rw-r--r--src/peerinfo/test_peerinfo_api.c5
-rw-r--r--src/statistics/gnunet-service-statistics.c332
-rw-r--r--src/statistics/statistics.h39
-rw-r--r--src/statistics/statistics_api.c365
-rw-r--r--src/statistics/test_statistics_api.c37
-rw-r--r--src/statistics/test_statistics_api_data.conf3
-rw-r--r--src/testing/test_testing_topology.c18
-rw-r--r--src/testing/testing.c6
-rw-r--r--src/topology/gnunet-daemon-topology.c7
-rw-r--r--src/transport/gnunet-service-transport.c11
-rw-r--r--src/util/server_nc.c26
34 files changed, 1230 insertions, 473 deletions
diff --git a/src/core/core.h b/src/core/core.h
index 88e6b748c..021aa4184 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -23,6 +23,7 @@
23 * @brief common internal definitions for core service 23 * @brief common internal definitions for core service
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26#include "gnunet_bandwidth_lib.h"
26#include "gnunet_crypto_lib.h" 27#include "gnunet_crypto_lib.h"
27#include "gnunet_time_lib.h" 28#include "gnunet_time_lib.h"
28 29
@@ -45,10 +46,11 @@
45#define GNUNET_CORE_OPTION_NOTHING 0 46#define GNUNET_CORE_OPTION_NOTHING 0
46#define GNUNET_CORE_OPTION_SEND_CONNECT 1 47#define GNUNET_CORE_OPTION_SEND_CONNECT 1
47#define GNUNET_CORE_OPTION_SEND_DISCONNECT 2 48#define GNUNET_CORE_OPTION_SEND_DISCONNECT 2
48#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 4 49#define GNUNET_CORE_OPTION_SEND_STATUS_CHANGE 4
49#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 8 50#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 8
50#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 16 51#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 16
51#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 32 52#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32
53#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 64
52 54
53 55
54/** 56/**
@@ -100,13 +102,12 @@ struct InitReplyMessage
100 102
101/** 103/**
102 * Message sent by the service to clients to notify them 104 * Message sent by the service to clients to notify them
103 * about a peer connecting or disconnecting. 105 * about a peer connecting.
104 */ 106 */
105struct ConnectNotifyMessage 107struct ConnectNotifyMessage
106{ 108{
107 /** 109 /**
108 * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT 110 * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
109 * or GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT.
110 */ 111 */
111 struct GNUNET_MessageHeader header; 112 struct GNUNET_MessageHeader header;
112 113
@@ -128,6 +129,49 @@ struct ConnectNotifyMessage
128}; 129};
129 130
130 131
132/**
133 * Message sent by the service to clients to notify them
134 * about a peer changing status.
135 */
136struct PeerStatusNotifyMessage
137{
138 /**
139 * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PEER_STATUS
140 */
141 struct GNUNET_MessageHeader header;
142
143 /**
144 * Distance to the peer.
145 */
146 uint32_t distance GNUNET_PACKED;
147
148 /**
149 * Currently observed latency.
150 */
151 struct GNUNET_TIME_RelativeNBO latency;
152
153 /**
154 * When the peer would time out (unless we see activity)
155 */
156 struct GNUNET_TIME_AbsoluteNBO timeout;
157
158 /**
159 * Available bandwidth from the peer.
160 */
161 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
162
163 /**
164 * Available bandwidth to the peer.
165 */
166 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
167
168 /**
169 * Identity of the peer.
170 */
171 struct GNUNET_PeerIdentity peer;
172
173};
174
131 175
132/** 176/**
133 * Message sent by the service to clients to notify them 177 * Message sent by the service to clients to notify them
diff --git a/src/core/core_api.c b/src/core/core_api.c
index d13166c14..5f21d8478 100644
--- a/src/core/core_api.c
+++ b/src/core/core_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -67,6 +67,11 @@ struct GNUNET_CORE_Handle
67 GNUNET_CORE_DisconnectEventHandler disconnects; 67 GNUNET_CORE_DisconnectEventHandler disconnects;
68 68
69 /** 69 /**
70 * Function to call whenever we're notified about a peer changing status.
71 */
72 GNUNET_CORE_PeerStatusEventHandler status_events;
73
74 /**
70 * Function to call whenever we receive an inbound message. 75 * Function to call whenever we receive an inbound message.
71 */ 76 */
72 GNUNET_CORE_MessageCallback inbound_notify; 77 GNUNET_CORE_MessageCallback inbound_notify;
@@ -381,6 +386,7 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg)
381 const struct DisconnectNotifyMessage *dnm; 386 const struct DisconnectNotifyMessage *dnm;
382 const struct NotifyTrafficMessage *ntm; 387 const struct NotifyTrafficMessage *ntm;
383 const struct GNUNET_MessageHeader *em; 388 const struct GNUNET_MessageHeader *em;
389 const struct PeerStatusNotifyMessage *psnm;
384 uint16_t msize; 390 uint16_t msize;
385 uint16_t et; 391 uint16_t et;
386 const struct GNUNET_CORE_MessageHandler *mh; 392 const struct GNUNET_CORE_MessageHandler *mh;
@@ -433,6 +439,26 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg)
433 h->disconnects (h->cls, 439 h->disconnects (h->cls,
434 &dnm->peer); 440 &dnm->peer);
435 break; 441 break;
442 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE:
443 if (NULL == h->status_events)
444 {
445 GNUNET_break (0);
446 break;
447 }
448 if (msize != sizeof (struct PeerStatusNotifyMessage))
449 {
450 GNUNET_break (0);
451 break;
452 }
453 psnm = (const struct PeerStatusNotifyMessage *) msg;
454 h->status_events (h->cls,
455 &psnm->peer,
456 GNUNET_TIME_relative_ntoh (psnm->latency),
457 ntohl (psnm->distance),
458 psnm->bandwidth_in,
459 psnm->bandwidth_out,
460 GNUNET_TIME_absolute_ntoh (psnm->timeout));
461 break;
436 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND: 462 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND:
437 if (msize < 463 if (msize <
438 sizeof (struct NotifyTrafficMessage) + 464 sizeof (struct NotifyTrafficMessage) +
@@ -658,6 +684,8 @@ transmit_start (void *cls, size_t size, void *buf)
658 opt |= GNUNET_CORE_OPTION_SEND_CONNECT; 684 opt |= GNUNET_CORE_OPTION_SEND_CONNECT;
659 if (h->disconnects != NULL) 685 if (h->disconnects != NULL)
660 opt |= GNUNET_CORE_OPTION_SEND_DISCONNECT; 686 opt |= GNUNET_CORE_OPTION_SEND_DISCONNECT;
687 if (h->status_events != NULL)
688 opt |= GNUNET_CORE_OPTION_SEND_STATUS_CHANGE;
661 if (h->inbound_notify != NULL) 689 if (h->inbound_notify != NULL)
662 { 690 {
663 if (h->inbound_hdr_only) 691 if (h->inbound_hdr_only)
@@ -717,6 +745,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
717 GNUNET_CORE_StartupCallback init, 745 GNUNET_CORE_StartupCallback init,
718 GNUNET_CORE_ConnectEventHandler connects, 746 GNUNET_CORE_ConnectEventHandler connects,
719 GNUNET_CORE_DisconnectEventHandler disconnects, 747 GNUNET_CORE_DisconnectEventHandler disconnects,
748 GNUNET_CORE_PeerStatusEventHandler status_events,
720 GNUNET_CORE_MessageCallback inbound_notify, 749 GNUNET_CORE_MessageCallback inbound_notify,
721 int inbound_hdr_only, 750 int inbound_hdr_only,
722 GNUNET_CORE_MessageCallback outbound_notify, 751 GNUNET_CORE_MessageCallback outbound_notify,
@@ -732,6 +761,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
732 h->init = init; 761 h->init = init;
733 h->connects = connects; 762 h->connects = connects;
734 h->disconnects = disconnects; 763 h->disconnects = disconnects;
764 h->status_events = status_events;
735 h->inbound_notify = inbound_notify; 765 h->inbound_notify = inbound_notify;
736 h->outbound_notify = outbound_notify; 766 h->outbound_notify = outbound_notify;
737 h->inbound_hdr_only = inbound_hdr_only; 767 h->inbound_hdr_only = inbound_hdr_only;
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index 4e5177ca3..8cd598e83 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -830,6 +830,43 @@ send_to_all_clients (const struct GNUNET_MessageHeader *msg,
830 830
831 831
832/** 832/**
833 * Function called by transport telling us that a peer
834 * changed status.
835 *
836 * @param peer the peer that changed status
837 */
838static void
839handle_peer_status_change (struct Neighbour *n)
840{
841 struct PeerStatusNotifyMessage psnm;
842
843 if (! n->is_connected)
844 return;
845#if DEBUG_CORE
846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
847 "Peer `%4s' changed status\n",
848 GNUNET_i2s (peer));
849#endif
850 psnm.header.size = htons (sizeof (struct PeerStatusNotifyMessage));
851 psnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE);
852 psnm.distance = htonl (n->last_distance);
853 psnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
854 psnm.timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (n->last_activity,
855 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
856 psnm.bandwidth_in = n->bw_in;
857 psnm.bandwidth_out = n->bw_out;
858 psnm.peer = n->peer;
859 send_to_all_clients (&psnm.header,
860 GNUNET_YES,
861 GNUNET_CORE_OPTION_SEND_STATUS_CHANGE);
862 GNUNET_STATISTICS_update (stats,
863 gettext_noop ("# peer status changes"),
864 1,
865 GNUNET_NO);
866}
867
868
869/**
833 * Handle CORE_INIT request. 870 * Handle CORE_INIT request.
834 */ 871 */
835static void 872static void
@@ -997,16 +1034,21 @@ handle_client_request_info (void *cls,
997 if (n->bw_out_internal_limit.value__ != rcm->limit_outbound.value__) 1034 if (n->bw_out_internal_limit.value__ != rcm->limit_outbound.value__)
998 { 1035 {
999 n->bw_out_internal_limit = rcm->limit_outbound; 1036 n->bw_out_internal_limit = rcm->limit_outbound;
1000 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit, 1037 if (n->bw_out.value__ != GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
1001 n->bw_out_external_limit); 1038 n->bw_out_external_limit).value__)
1002 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_recv_window, 1039 {
1003 n->bw_out); 1040 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
1004 GNUNET_TRANSPORT_set_quota (transport, 1041 n->bw_out_external_limit);
1005 &n->peer, 1042 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_recv_window,
1006 n->bw_in, 1043 n->bw_out);
1007 n->bw_out, 1044 GNUNET_TRANSPORT_set_quota (transport,
1008 GNUNET_TIME_UNIT_FOREVER_REL, 1045 &n->peer,
1009 NULL, NULL); 1046 n->bw_in,
1047 n->bw_out,
1048 GNUNET_TIME_UNIT_FOREVER_REL,
1049 NULL, NULL);
1050 handle_peer_status_change (n);
1051 }
1010 } 1052 }
1011 if (want_reserv < 0) 1053 if (want_reserv < 0)
1012 { 1054 {
@@ -2359,13 +2401,11 @@ handle_client_request_connect (void *cls,
2359 * @param cls the 'struct Neighbour' to retry sending the key for 2401 * @param cls the 'struct Neighbour' to retry sending the key for
2360 * @param peer the peer for which this is the HELLO 2402 * @param peer the peer for which this is the HELLO
2361 * @param hello HELLO message of that peer 2403 * @param hello HELLO message of that peer
2362 * @param trust amount of trust we currently have in that peer
2363 */ 2404 */
2364static void 2405static void
2365process_hello_retry_send_key (void *cls, 2406process_hello_retry_send_key (void *cls,
2366 const struct GNUNET_PeerIdentity *peer, 2407 const struct GNUNET_PeerIdentity *peer,
2367 const struct GNUNET_HELLO_Message *hello, 2408 const struct GNUNET_HELLO_Message *hello)
2368 uint32_t trust)
2369{ 2409{
2370 struct Neighbour *n = cls; 2410 struct Neighbour *n = cls;
2371 2411
@@ -2516,7 +2556,6 @@ send_key (struct Neighbour *n)
2516 GNUNET_assert (n->pitr == NULL); 2556 GNUNET_assert (n->pitr == NULL);
2517 n->pitr = GNUNET_PEERINFO_iterate (peerinfo, 2557 n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
2518 &n->peer, 2558 &n->peer,
2519 0,
2520 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20), 2559 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20),
2521 &process_hello_retry_send_key, n); 2560 &process_hello_retry_send_key, n);
2522 return; 2561 return;
@@ -2666,13 +2705,11 @@ handle_set_key (struct Neighbour *n,
2666 * @param cls pointer to the set key message 2705 * @param cls pointer to the set key message
2667 * @param peer the peer for which this is the HELLO 2706 * @param peer the peer for which this is the HELLO
2668 * @param hello HELLO message of that peer 2707 * @param hello HELLO message of that peer
2669 * @param trust amount of trust we currently have in that peer
2670 */ 2708 */
2671static void 2709static void
2672process_hello_retry_handle_set_key (void *cls, 2710process_hello_retry_handle_set_key (void *cls,
2673 const struct GNUNET_PeerIdentity *peer, 2711 const struct GNUNET_PeerIdentity *peer,
2674 const struct GNUNET_HELLO_Message *hello, 2712 const struct GNUNET_HELLO_Message *hello)
2675 uint32_t trust)
2676{ 2713{
2677 struct Neighbour *n = cls; 2714 struct Neighbour *n = cls;
2678 struct SetKeyMessage *sm = n->skm; 2715 struct SetKeyMessage *sm = n->skm;
@@ -2922,6 +2959,7 @@ handle_pong (struct Neighbour *n,
2922 GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2), 2959 GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
2923 &send_keep_alive, 2960 &send_keep_alive,
2924 n); 2961 n);
2962 handle_peer_status_change (n);
2925 break; 2963 break;
2926 default: 2964 default:
2927 GNUNET_break (0); 2965 GNUNET_break (0);
@@ -2974,7 +3012,6 @@ handle_set_key (struct Neighbour *n, const struct SetKeyMessage *m)
2974 n->skm = m_cpy; 3012 n->skm = m_cpy;
2975 n->pitr = GNUNET_PEERINFO_iterate (peerinfo, 3013 n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
2976 &n->peer, 3014 &n->peer,
2977 0,
2978 GNUNET_TIME_UNIT_MINUTES, 3015 GNUNET_TIME_UNIT_MINUTES,
2979 &process_hello_retry_handle_set_key, n); 3016 &process_hello_retry_handle_set_key, n);
2980 GNUNET_STATISTICS_update (stats, 3017 GNUNET_STATISTICS_update (stats,
@@ -3364,7 +3401,8 @@ handle_encrypted_message (struct Neighbour *n,
3364 GNUNET_STATISTICS_set (stats, 3401 GNUNET_STATISTICS_set (stats,
3365 gettext_noop ("# bytes of payload decrypted"), 3402 gettext_noop ("# bytes of payload decrypted"),
3366 size - sizeof (struct EncryptedMessage), 3403 size - sizeof (struct EncryptedMessage),
3367 GNUNET_NO); 3404 GNUNET_NO);
3405 handle_peer_status_change (n);
3368 if (GNUNET_OK != GNUNET_SERVER_mst_receive (mst, 3406 if (GNUNET_OK != GNUNET_SERVER_mst_receive (mst,
3369 n, 3407 n,
3370 &buf[sizeof (struct EncryptedMessage)], 3408 &buf[sizeof (struct EncryptedMessage)],
@@ -3396,6 +3434,7 @@ handle_transport_receive (void *cls,
3396 int up; 3434 int up;
3397 uint16_t type; 3435 uint16_t type;
3398 uint16_t size; 3436 uint16_t size;
3437 int changed;
3399 3438
3400#if DEBUG_CORE 3439#if DEBUG_CORE
3401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -3411,6 +3450,7 @@ handle_transport_receive (void *cls,
3411 n = find_neighbour (peer); 3450 n = find_neighbour (peer);
3412 if (n == NULL) 3451 if (n == NULL)
3413 n = create_neighbour (peer); 3452 n = create_neighbour (peer);
3453 changed = (latency.value != n->last_latency.value) || (distance != n->last_distance);
3414 n->last_latency = latency; 3454 n->last_latency = latency;
3415 n->last_distance = distance; 3455 n->last_distance = distance;
3416 up = (n->status == PEER_STATE_KEY_CONFIRMED); 3456 up = (n->status == PEER_STATE_KEY_CONFIRMED);
@@ -3496,6 +3536,7 @@ handle_transport_receive (void *cls,
3496 { 3536 {
3497 now = GNUNET_TIME_absolute_get (); 3537 now = GNUNET_TIME_absolute_get ();
3498 n->last_activity = now; 3538 n->last_activity = now;
3539 changed = GNUNET_YES;
3499 if (!up) 3540 if (!up)
3500 { 3541 {
3501 GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"), 1, GNUNET_NO); 3542 GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"), 1, GNUNET_NO);
@@ -3509,6 +3550,8 @@ handle_transport_receive (void *cls,
3509 &send_keep_alive, 3550 &send_keep_alive,
3510 n); 3551 n);
3511 } 3552 }
3553 if (changed)
3554 handle_peer_status_change (n);
3512} 3555}
3513 3556
3514 3557
@@ -3591,6 +3634,7 @@ neighbour_quota_update (void *cls,
3591 n->bw_out, 3634 n->bw_out,
3592 GNUNET_TIME_UNIT_FOREVER_REL, 3635 GNUNET_TIME_UNIT_FOREVER_REL,
3593 NULL, NULL); 3636 NULL, NULL);
3637 handle_peer_status_change (n);
3594 } 3638 }
3595 schedule_quota_update (n); 3639 schedule_quota_update (n);
3596} 3640}
diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c
index c488a5153..ad82d0a1d 100644
--- a/src/core/test_core_api.c
+++ b/src/core/test_core_api.c
@@ -228,6 +228,7 @@ init_notify (void *cls,
228 &init_notify, 228 &init_notify,
229 &connect_notify, 229 &connect_notify,
230 &disconnect_notify, 230 &disconnect_notify,
231 NULL,
231 &inbound_notify, 232 &inbound_notify,
232 GNUNET_YES, 233 GNUNET_YES,
233 &outbound_notify, GNUNET_YES, handlers); 234 &outbound_notify, GNUNET_YES, handlers);
@@ -321,6 +322,7 @@ run (void *cls,
321 &init_notify, 322 &init_notify,
322 &connect_notify, 323 &connect_notify,
323 &disconnect_notify, 324 &disconnect_notify,
325 NULL,
324 &inbound_notify, 326 &inbound_notify,
325 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); 327 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);
326} 328}
diff --git a/src/core/test_core_api_reliability.c b/src/core/test_core_api_reliability.c
index 6d3ae04dc..c2375620a 100644
--- a/src/core/test_core_api_reliability.c
+++ b/src/core/test_core_api_reliability.c
@@ -375,6 +375,7 @@ init_notify (void *cls,
375 &init_notify, 375 &init_notify,
376 &connect_notify, 376 &connect_notify,
377 &disconnect_notify, 377 &disconnect_notify,
378 NULL,
378 &inbound_notify, 379 &inbound_notify,
379 GNUNET_YES, 380 GNUNET_YES,
380 &outbound_notify, GNUNET_YES, handlers); 381 &outbound_notify, GNUNET_YES, handlers);
@@ -468,6 +469,7 @@ run (void *cls,
468 &init_notify, 469 &init_notify,
469 &connect_notify, 470 &connect_notify,
470 &disconnect_notify, 471 &disconnect_notify,
472 NULL,
471 &inbound_notify, 473 &inbound_notify,
472 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); 474 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);
473} 475}
diff --git a/src/core/test_core_api_start_only.c b/src/core/test_core_api_start_only.c
index 4195bdc58..4155bf5d4 100644
--- a/src/core/test_core_api_start_only.c
+++ b/src/core/test_core_api_start_only.c
@@ -133,6 +133,7 @@ init_notify (void *cls,
133 &init_notify, 133 &init_notify,
134 &connect_notify, 134 &connect_notify,
135 &disconnect_notify, 135 &disconnect_notify,
136 NULL,
136 &inbound_notify, 137 &inbound_notify,
137 GNUNET_YES, 138 GNUNET_YES,
138 &outbound_notify, GNUNET_YES, handlers); 139 &outbound_notify, GNUNET_YES, handlers);
@@ -182,6 +183,7 @@ run (void *cls,
182 &init_notify, 183 &init_notify,
183 &connect_notify, 184 &connect_notify,
184 &disconnect_notify, 185 &disconnect_notify,
186 NULL,
185 &inbound_notify, 187 &inbound_notify,
186 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); 188 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);
187} 189}
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c
index a310cc944..32c01e384 100644
--- a/src/dht/gnunet-service-dht.c
+++ b/src/dht/gnunet-service-dht.c
@@ -834,6 +834,7 @@ run (void *cls,
834 &core_init, /* Call core_init once connected */ 834 &core_init, /* Call core_init once connected */
835 &handle_core_connect, /* Don't care about connects */ 835 &handle_core_connect, /* Don't care about connects */
836 NULL, /* Don't care about disconnects */ 836 NULL, /* Don't care about disconnects */
837 NULL, /* Don't care about peer status changes */
837 NULL, /* Don't want notified about all incoming messages */ 838 NULL, /* Don't want notified about all incoming messages */
838 GNUNET_NO, /* For header only inbound notification */ 839 GNUNET_NO, /* For header only inbound notification */
839 NULL, /* Don't want notified about all outbound messages */ 840 NULL, /* Don't want notified about all outbound messages */
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c
index b16f12938..9fb008237 100644
--- a/src/dv/gnunet-service-dv.c
+++ b/src/dv/gnunet-service-dv.c
@@ -2755,12 +2755,11 @@ static int add_all_direct_neighbors (void *cls,
2755 * @param cls closure 2755 * @param cls closure
2756 * @param peer id of the peer, NULL for last call 2756 * @param peer id of the peer, NULL for last call
2757 * @param hello hello message for the peer (can be NULL) 2757 * @param hello hello message for the peer (can be NULL)
2758 * @param trust amount of trust we have in the peer
2759 */ 2758 */
2760static void 2759static void
2761process_peerinfo (void *cls, 2760process_peerinfo (void *cls,
2762 const struct GNUNET_PeerIdentity *peer, 2761 const struct GNUNET_PeerIdentity *peer,
2763 const struct GNUNET_HELLO_Message *hello, uint32_t trust) 2762 const struct GNUNET_HELLO_Message *hello)
2764{ 2763{
2765 struct PeerIteratorContext *peerinfo_iterator = cls; 2764 struct PeerIteratorContext *peerinfo_iterator = cls;
2766 struct DirectNeighbor *neighbor = peerinfo_iterator->neighbor; 2765 struct DirectNeighbor *neighbor = peerinfo_iterator->neighbor;
@@ -2779,7 +2778,6 @@ process_peerinfo (void *cls,
2779#endif 2778#endif
2780 peerinfo_iterator->ic = GNUNET_PEERINFO_iterate(peerinfo_handle, 2779 peerinfo_iterator->ic = GNUNET_PEERINFO_iterate(peerinfo_handle,
2781 &peerinfo_iterator->neighbor->identity, 2780 &peerinfo_iterator->neighbor->identity,
2782 0,
2783 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3), 2781 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
2784 &process_peerinfo, 2782 &process_peerinfo,
2785 peerinfo_iterator); 2783 peerinfo_iterator);
@@ -2856,7 +2854,6 @@ void handle_core_connect (void *cls,
2856 peerinfo_iterator->neighbor = neighbor; 2854 peerinfo_iterator->neighbor = neighbor;
2857 peerinfo_iterator->ic = GNUNET_PEERINFO_iterate (peerinfo_handle, 2855 peerinfo_iterator->ic = GNUNET_PEERINFO_iterate (peerinfo_handle,
2858 peer, 2856 peer,
2859 0,
2860 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3), 2857 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
2861 &process_peerinfo, 2858 &process_peerinfo,
2862 peerinfo_iterator); 2859 peerinfo_iterator);
@@ -2988,6 +2985,7 @@ run (void *cls,
2988 &core_init, 2985 &core_init,
2989 &handle_core_connect, 2986 &handle_core_connect,
2990 &handle_core_disconnect, 2987 &handle_core_disconnect,
2988 NULL,
2991 NULL, 2989 NULL,
2992 GNUNET_NO, 2990 GNUNET_NO,
2993 NULL, 2991 NULL,
diff --git a/src/dv/test_transport_api_dv.c b/src/dv/test_transport_api_dv.c
index 8157d00e7..3e66388fe 100644
--- a/src/dv/test_transport_api_dv.c
+++ b/src/dv/test_transport_api_dv.c
@@ -534,14 +534,14 @@ init_notify_peer1 (void *cls,
534 * Connect to the receiving peer 534 * Connect to the receiving peer
535 */ 535 */
536 pos->peer2handle = GNUNET_CORE_connect (sched, 536 pos->peer2handle = GNUNET_CORE_connect (sched,
537 pos->peer2->cfg, 537 pos->peer2->cfg,
538 TIMEOUT, 538 TIMEOUT,
539 pos, 539 pos,
540 &init_notify_peer2, 540 &init_notify_peer2,
541 NULL, 541 NULL,
542 NULL, 542 NULL,
543 NULL, 543 NULL, NULL,
544 GNUNET_YES, NULL, GNUNET_YES, handlers); 544 GNUNET_YES, NULL, GNUNET_YES, handlers);
545 545
546} 546}
547 547
@@ -578,7 +578,7 @@ send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
578 TIMEOUT, 578 TIMEOUT,
579 pos, 579 pos,
580 &init_notify_peer1, 580 &init_notify_peer1,
581 NULL, 581 NULL, NULL,
582 NULL, 582 NULL,
583 NULL, 583 NULL,
584 GNUNET_NO, NULL, GNUNET_NO, no_handlers); 584 GNUNET_NO, NULL, GNUNET_NO, no_handlers);
@@ -893,7 +893,7 @@ peers_started_callback (void *cls,
893 GNUNET_assert(GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_put(peer_daemon_hash, &id->hashPubKey, d, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 893 GNUNET_assert(GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_put(peer_daemon_hash, &id->hashPubKey, d, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
894 894
895 new_peer = GNUNET_malloc(sizeof(struct PeerContext)); 895 new_peer = GNUNET_malloc(sizeof(struct PeerContext));
896 new_peer->peer_handle = GNUNET_CORE_connect(sched, cfg, GNUNET_TIME_UNIT_FOREVER_REL, d, NULL, &all_connect_handler, NULL, NULL, GNUNET_NO, NULL, GNUNET_NO, no_handlers); 896 new_peer->peer_handle = GNUNET_CORE_connect(sched, cfg, GNUNET_TIME_UNIT_FOREVER_REL, d, NULL, &all_connect_handler, NULL, NULL, NULL, GNUNET_NO, NULL, GNUNET_NO, no_handlers);
897 new_peer->daemon = d; 897 new_peer->daemon = d;
898 new_peer->next = all_peers; 898 new_peer->next = all_peers;
899 all_peers = new_peer; 899 all_peers = new_peer;
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index e2d90f786..ea79d0711 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -55,6 +55,12 @@
55#define MAX_QUEUE_PER_PEER 16 55#define MAX_QUEUE_PER_PEER 16
56 56
57/** 57/**
58 * How often do we flush trust values to disk?
59 */
60#define TRUST_FLUSH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
61
62
63/**
58 * Inverse of the probability that we will submit the same query 64 * Inverse of the probability that we will submit the same query
59 * to the same peer again. If the same peer already got the query 65 * to the same peer again. If the same peer already got the query
60 * repeatedly recently, the probability is multiplied by the inverse 66 * repeatedly recently, the probability is multiplied by the inverse
@@ -211,9 +217,14 @@ struct ConnectedPeer
211 uint64_t inc_preference; 217 uint64_t inc_preference;
212 218
213 /** 219 /**
214 * Trust delta to still commit to the system. 220 * Trust rating for this peer
215 */ 221 */
216 uint32_t trust_delta; 222 uint32_t trust;
223
224 /**
225 * Trust rating for this peer on disk.
226 */
227 uint32_t disk_trust;
217 228
218 /** 229 /**
219 * The peer's identity. 230 * The peer's identity.
@@ -680,6 +691,11 @@ static struct MigrationReadyBlock *mig_tail;
680static struct GNUNET_DATASTORE_QueueEntry *mig_qe; 691static struct GNUNET_DATASTORE_QueueEntry *mig_qe;
681 692
682/** 693/**
694 * Where do we store trust information?
695 */
696static char *trustDirectory;
697
698/**
683 * ID of task that collects blocks for migration. 699 * ID of task that collects blocks for migration.
684 */ 700 */
685static GNUNET_SCHEDULER_TaskIdentifier mig_task; 701static GNUNET_SCHEDULER_TaskIdentifier mig_task;
@@ -702,6 +718,24 @@ static int active_migration;
702 718
703 719
704/** 720/**
721 * Get the filename under which we would store the GNUNET_HELLO_Message
722 * for the given host and protocol.
723 * @return filename of the form DIRECTORY/HOSTID
724 */
725static char *
726get_trust_filename (const struct GNUNET_PeerIdentity *id)
727{
728 struct GNUNET_CRYPTO_HashAsciiEncoded fil;
729 char *fn;
730
731 GNUNET_CRYPTO_hash_to_enc (&id->hashPubKey, &fil);
732 GNUNET_asprintf (&fn, "%s%s%s", trustDirectory, DIR_SEPARATOR_STR, &fil);
733 return fn;
734}
735
736
737
738/**
705 * Transmit messages by copying it to the target buffer 739 * Transmit messages by copying it to the target buffer
706 * "buf". "buf" will be NULL and "size" zero if the socket was closed 740 * "buf". "buf" will be NULL and "size" zero if the socket was closed
707 * for writing in the meantime. In that case, do nothing 741 * for writing in the meantime. In that case, do nothing
@@ -1148,9 +1182,18 @@ peer_connect_handler (void *cls,
1148{ 1182{
1149 struct ConnectedPeer *cp; 1183 struct ConnectedPeer *cp;
1150 struct MigrationReadyBlock *pos; 1184 struct MigrationReadyBlock *pos;
1185 char *fn;
1186 uint32_t trust;
1151 1187
1152 cp = GNUNET_malloc (sizeof (struct ConnectedPeer)); 1188 cp = GNUNET_malloc (sizeof (struct ConnectedPeer));
1153 cp->pid = GNUNET_PEER_intern (peer); 1189 cp->pid = GNUNET_PEER_intern (peer);
1190
1191 fn = get_trust_filename (peer);
1192 if ((GNUNET_DISK_file_test (fn) == GNUNET_YES) &&
1193 (sizeof (trust) == GNUNET_DISK_fn_read (fn, &trust, sizeof (trust))))
1194 cp->disk_trust = cp->trust = ntohl (trust);
1195 GNUNET_free (fn);
1196
1154 GNUNET_break (GNUNET_OK == 1197 GNUNET_break (GNUNET_OK ==
1155 GNUNET_CONTAINER_multihashmap_put (connected_peers, 1198 GNUNET_CONTAINER_multihashmap_put (connected_peers,
1156 &peer->hashPubKey, 1199 &peer->hashPubKey,
@@ -1166,6 +1209,105 @@ peer_connect_handler (void *cls,
1166} 1209}
1167 1210
1168 1211
1212/**
1213 * Increase the host credit by a value.
1214 *
1215 * @param host which peer to change the trust value on
1216 * @param value is the int value by which the
1217 * host credit is to be increased or decreased
1218 * @returns the actual change in trust (positive or negative)
1219 */
1220static int
1221change_host_trust (struct ConnectedPeer *host, int value)
1222{
1223 unsigned int old_trust;
1224
1225 if (value == 0)
1226 return 0;
1227 GNUNET_assert (host != NULL);
1228 old_trust = host->trust;
1229 if (value > 0)
1230 {
1231 if (host->trust + value < host->trust)
1232 {
1233 value = UINT32_MAX - host->trust;
1234 host->trust = UINT32_MAX;
1235 }
1236 else
1237 host->trust += value;
1238 }
1239 else
1240 {
1241 if (host->trust < -value)
1242 {
1243 value = -host->trust;
1244 host->trust = 0;
1245 }
1246 else
1247 host->trust += value;
1248 }
1249 return value;
1250}
1251
1252
1253/**
1254 * Write host-trust information to a file - flush the buffer entry!
1255 */
1256static int
1257flush_trust (void *cls,
1258 const GNUNET_HashCode *key,
1259 void *value)
1260{
1261 struct ConnectedPeer *host = value;
1262 char *fn;
1263 uint32_t trust;
1264 struct GNUNET_PeerIdentity pid;
1265
1266 if (host->trust == host->disk_trust)
1267 return GNUNET_OK; /* unchanged */
1268 GNUNET_PEER_resolve (host->pid,
1269 &pid);
1270 fn = get_trust_filename (&pid);
1271 if (host->trust == 0)
1272 {
1273 if ((0 != UNLINK (fn)) && (errno != ENOENT))
1274 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
1275 GNUNET_ERROR_TYPE_BULK, "unlink", fn);
1276 }
1277 else
1278 {
1279 trust = htonl (host->trust);
1280 if (sizeof(uint32_t) == GNUNET_DISK_fn_write (fn, &trust,
1281 sizeof(uint32_t),
1282 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE
1283 | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ))
1284 host->disk_trust = host->trust;
1285 }
1286 GNUNET_free (fn);
1287 return GNUNET_OK;
1288}
1289
1290/**
1291 * Call this method periodically to scan data/hosts for new hosts.
1292 */
1293static void
1294cron_flush_trust (void *cls,
1295 const struct GNUNET_SCHEDULER_TaskContext *tc)
1296{
1297
1298 if (NULL == connected_peers)
1299 return;
1300 GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
1301 &flush_trust,
1302 NULL);
1303 if (NULL == tc)
1304 return;
1305 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1306 return;
1307 GNUNET_SCHEDULER_add_delayed (tc->sched,
1308 TRUST_FLUSH_FREQ, &cron_flush_trust, NULL);
1309}
1310
1169 1311
1170/** 1312/**
1171 * Free (each) request made by the peer. 1313 * Free (each) request made by the peer.
@@ -1253,7 +1395,7 @@ peer_disconnect_handler (void *cls,
1253 &consider_migration, 1395 &consider_migration,
1254 pos); 1396 pos);
1255 } 1397 }
1256 if (cp->trust_delta > 0) 1398 if (cp->trust > 0)
1257 { 1399 {
1258 /* FIXME: push trust back to peerinfo! 1400 /* FIXME: push trust back to peerinfo!
1259 (need better peerinfo API!) */ 1401 (need better peerinfo API!) */
@@ -1400,6 +1542,7 @@ shutdown_task (void *cls,
1400 while (client_list != NULL) 1542 while (client_list != NULL)
1401 handle_client_disconnect (NULL, 1543 handle_client_disconnect (NULL,
1402 client_list->client); 1544 client_list->client);
1545 cron_flush_trust (NULL, NULL);
1403 GNUNET_CONTAINER_multihashmap_iterate (connected_peers, 1546 GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
1404 &clean_peer, 1547 &clean_peer,
1405 NULL); 1548 NULL);
@@ -1430,6 +1573,8 @@ shutdown_task (void *cls,
1430 dsh = NULL; 1573 dsh = NULL;
1431 sched = NULL; 1574 sched = NULL;
1432 cfg = NULL; 1575 cfg = NULL;
1576 GNUNET_free_non_null (trustDirectory);
1577 trustDirectory = NULL;
1433} 1578}
1434 1579
1435 1580
@@ -2674,7 +2819,7 @@ handle_p2p_put (void *cls,
2674 if (prq.sender != NULL) 2819 if (prq.sender != NULL)
2675 { 2820 {
2676 prq.sender->inc_preference += CONTENT_BANDWIDTH_VALUE + 1000 * prq.priority; 2821 prq.sender->inc_preference += CONTENT_BANDWIDTH_VALUE + 1000 * prq.priority;
2677 prq.sender->trust_delta += prq.priority; 2822 prq.sender->trust += prq.priority;
2678 } 2823 }
2679 if (GNUNET_YES == active_migration) 2824 if (GNUNET_YES == active_migration)
2680 { 2825 {
@@ -2954,13 +3099,9 @@ static uint32_t
2954bound_priority (uint32_t prio_in, 3099bound_priority (uint32_t prio_in,
2955 struct ConnectedPeer *cp) 3100 struct ConnectedPeer *cp)
2956{ 3101{
2957 if (cp->trust_delta > prio_in) 3102 /* FIXME: check if load is low and we
2958 { 3103 hence should not charge... */
2959 cp->trust_delta -= prio_in; 3104 return change_host_trust (cp, prio_in);
2960 return prio_in;
2961 }
2962 // FIXME: get out trust in the target peer from peerinfo!
2963 return 0;
2964} 3105}
2965 3106
2966 3107
@@ -3510,6 +3651,7 @@ main_init (struct GNUNET_SCHEDULER_Handle *s,
3510 NULL, 3651 NULL,
3511 &peer_connect_handler, 3652 &peer_connect_handler,
3512 &peer_disconnect_handler, 3653 &peer_disconnect_handler,
3654 NULL,
3513 NULL, GNUNET_NO, 3655 NULL, GNUNET_NO,
3514 NULL, GNUNET_NO, 3656 NULL, GNUNET_NO,
3515 p2p_handlers); 3657 p2p_handlers);
@@ -3543,6 +3685,17 @@ main_init (struct GNUNET_SCHEDULER_Handle *s,
3543 GNUNET_SERVER_disconnect_notify (server, 3685 GNUNET_SERVER_disconnect_notify (server,
3544 &handle_client_disconnect, 3686 &handle_client_disconnect,
3545 NULL); 3687 NULL);
3688 GNUNET_assert (GNUNET_OK ==
3689 GNUNET_CONFIGURATION_get_value_filename (cfg,
3690 "fs",
3691 "TRUST",
3692 &trustDirectory));
3693 GNUNET_DISK_directory_create (trustDirectory);
3694 GNUNET_SCHEDULER_add_with_priority (sched,
3695 GNUNET_SCHEDULER_PRIORITY_HIGH,
3696 &cron_flush_trust, NULL);
3697
3698
3546 GNUNET_SERVER_add_handlers (server, handlers); 3699 GNUNET_SERVER_add_handlers (server, handlers);
3547 GNUNET_SCHEDULER_add_delayed (sched, 3700 GNUNET_SCHEDULER_add_delayed (sched,
3548 GNUNET_TIME_UNIT_FOREVER_REL, 3701 GNUNET_TIME_UNIT_FOREVER_REL,
diff --git a/src/hostlist/gnunet-daemon-hostlist.c b/src/hostlist/gnunet-daemon-hostlist.c
index ffeff0882..52c996aed 100644
--- a/src/hostlist/gnunet-daemon-hostlist.c
+++ b/src/hostlist/gnunet-daemon-hostlist.c
@@ -274,7 +274,7 @@ run (void *cls,
274 GNUNET_TIME_UNIT_FOREVER_REL, 274 GNUNET_TIME_UNIT_FOREVER_REL,
275 NULL, 275 NULL,
276 &core_init, 276 &core_init,
277 &connect_handler, &disconnect_handler, 277 &connect_handler, &disconnect_handler, NULL,
278 NULL, GNUNET_NO, 278 NULL, GNUNET_NO,
279 NULL, GNUNET_NO, 279 NULL, GNUNET_NO,
280 learning? learn_handlers : no_learn_handlers); 280 learning? learn_handlers : no_learn_handlers);
diff --git a/src/hostlist/hostlist-server.c b/src/hostlist/hostlist-server.c
index 58daf0401..87fae74e3 100644
--- a/src/hostlist/hostlist-server.c
+++ b/src/hostlist/hostlist-server.c
@@ -183,8 +183,7 @@ check_has_addr (void *cls,
183static void 183static void
184host_processor (void *cls, 184host_processor (void *cls,
185 const struct GNUNET_PeerIdentity * peer, 185 const struct GNUNET_PeerIdentity * peer,
186 const struct GNUNET_HELLO_Message *hello, 186 const struct GNUNET_HELLO_Message *hello)
187 uint32_t trust)
188{ 187{
189 struct HostSet *results = cls; 188 struct HostSet *results = cls;
190 size_t old; 189 size_t old;
@@ -447,13 +446,11 @@ disconnect_handler (void *cls,
447 * @param cls closure (not used) 446 * @param cls closure (not used)
448 * @param peer potential peer to connect to 447 * @param peer potential peer to connect to
449 * @param hello HELLO for this peer (or NULL) 448 * @param hello HELLO for this peer (or NULL)
450 * @param trust how much we trust the peer (not used)
451 */ 449 */
452static void 450static void
453process_notify (void *cls, 451process_notify (void *cls,
454 const struct GNUNET_PeerIdentity *peer, 452 const struct GNUNET_PeerIdentity *peer,
455 const struct GNUNET_HELLO_Message *hello, 453 const struct GNUNET_HELLO_Message *hello)
456 uint32_t trust)
457{ 454{
458 struct HostSet *results; 455 struct HostSet *results;
459#if DEBUG_HOSTLIST_SERVER 456#if DEBUG_HOSTLIST_SERVER
@@ -464,7 +461,6 @@ process_notify (void *cls,
464 GNUNET_assert (peerinfo != NULL); 461 GNUNET_assert (peerinfo != NULL);
465 pitr = GNUNET_PEERINFO_iterate (peerinfo, 462 pitr = GNUNET_PEERINFO_iterate (peerinfo,
466 NULL, 463 NULL,
467 0,
468 GNUNET_TIME_UNIT_MINUTES, 464 GNUNET_TIME_UNIT_MINUTES,
469 &host_processor, 465 &host_processor,
470 results); 466 results);
diff --git a/src/hostlist/test_gnunet_daemon_hostlist_learning.c b/src/hostlist/test_gnunet_daemon_hostlist_learning.c
index 96390373f..d1a04ffe8 100644
--- a/src/hostlist/test_gnunet_daemon_hostlist_learning.c
+++ b/src/hostlist/test_gnunet_daemon_hostlist_learning.c
@@ -383,13 +383,13 @@ setup_learn_peer (struct PeerContext *p, const char *cfgname)
383 if ( NULL != filename) GNUNET_free ( filename ); 383 if ( NULL != filename) GNUNET_free ( filename );
384 384
385 p->core = GNUNET_CORE_connect (sched, p->cfg, 385 p->core = GNUNET_CORE_connect (sched, p->cfg,
386 GNUNET_TIME_UNIT_FOREVER_REL, 386 GNUNET_TIME_UNIT_FOREVER_REL,
387 NULL, 387 NULL,
388 NULL, 388 NULL,
389 NULL, NULL, 389 NULL, NULL, NULL,
390 NULL, GNUNET_NO, 390 NULL, GNUNET_NO,
391 NULL, GNUNET_NO, 391 NULL, GNUNET_NO,
392 learn_handlers ); 392 learn_handlers );
393 GNUNET_assert ( NULL != p->core ); 393 GNUNET_assert ( NULL != p->core );
394 p->stats = GNUNET_STATISTICS_create (sched, "hostlist", p->cfg); 394 p->stats = GNUNET_STATISTICS_create (sched, "hostlist", p->cfg);
395 GNUNET_assert ( NULL != p->stats ); 395 GNUNET_assert ( NULL != p->stats );
diff --git a/src/include/gnunet_core_service.h b/src/include/gnunet_core_service.h
index 069bf5202..2434e3770 100644
--- a/src/include/gnunet_core_service.h
+++ b/src/include/gnunet_core_service.h
@@ -64,6 +64,26 @@ typedef void (*GNUNET_CORE_ConnectEventHandler) (void *cls,
64 struct GNUNET_TIME_Relative latency, 64 struct GNUNET_TIME_Relative latency,
65 uint32_t distance); 65 uint32_t distance);
66 66
67/**
68 * Method called whenever a given peer has a status change.
69 *
70 * @param cls closure
71 * @param peer peer identity this notification is about
72 * @param latency reported latency of the connection with 'other'
73 * @param distance reported distance (DV) to 'other'
74 * @param bandwidth_in available amount of inbound bandwidth
75 * @param bandwidth_out available amount of outbound bandwidth
76 * @param timeout absolute time when this peer will time out
77 * unless we see some further activity from it
78 */
79typedef void (*GNUNET_CORE_PeerStatusEventHandler) (void *cls,
80 const struct
81 GNUNET_PeerIdentity * peer,
82 struct GNUNET_TIME_Relative latency,
83 uint32_t distance,
84 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
85 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
86 struct GNUNET_TIME_Absolute timeout);
67 87
68 88
69/** 89/**
@@ -166,6 +186,7 @@ typedef void
166 * connected to the core service; note that timeout is only meaningful if init is not NULL 186 * connected to the core service; note that timeout is only meaningful if init is not NULL
167 * @param connects function to call on peer connect, can be NULL 187 * @param connects function to call on peer connect, can be NULL
168 * @param disconnects function to call on peer disconnect / timeout, can be NULL 188 * @param disconnects function to call on peer disconnect / timeout, can be NULL
189 * @param status_events function to call on peer status changes, can be NULL
169 * @param inbound_notify function to call for all inbound messages, can be NULL 190 * @param inbound_notify function to call for all inbound messages, can be NULL
170 * note that the core is allowed to drop notifications about inbound 191 * note that the core is allowed to drop notifications about inbound
171 * messages if the client does not process them fast enough (for this 192 * messages if the client does not process them fast enough (for this
@@ -201,6 +222,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
201 GNUNET_CORE_StartupCallback init, 222 GNUNET_CORE_StartupCallback init,
202 GNUNET_CORE_ConnectEventHandler connects, 223 GNUNET_CORE_ConnectEventHandler connects,
203 GNUNET_CORE_DisconnectEventHandler disconnects, 224 GNUNET_CORE_DisconnectEventHandler disconnects,
225 GNUNET_CORE_PeerStatusEventHandler status_events,
204 GNUNET_CORE_MessageCallback inbound_notify, 226 GNUNET_CORE_MessageCallback inbound_notify,
205 int inbound_hdr_only, 227 int inbound_hdr_only,
206 GNUNET_CORE_MessageCallback outbound_notify, 228 GNUNET_CORE_MessageCallback outbound_notify,
diff --git a/src/include/gnunet_peerinfo_service.h b/src/include/gnunet_peerinfo_service.h
index db5cc37ba..d88c6fb41 100644
--- a/src/include/gnunet_peerinfo_service.h
+++ b/src/include/gnunet_peerinfo_service.h
@@ -20,8 +20,7 @@
20/** 20/**
21 * @file include/gnunet_peerinfo_service.h 21 * @file include/gnunet_peerinfo_service.h
22 * @brief Code to maintain the list of currently known hosts 22 * @brief Code to maintain the list of currently known hosts
23 * (in memory structure of data/hosts) and their trust ratings 23 * (in memory structure of data/hosts).
24 * (in memory structure of data/trust)
25 * @author Christian Grothoff 24 * @author Christian Grothoff
26 */ 25 */
27 26
@@ -98,13 +97,11 @@ GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h,
98 * @param cls closure 97 * @param cls closure
99 * @param peer id of the peer, NULL for last call 98 * @param peer id of the peer, NULL for last call
100 * @param hello hello message for the peer (can be NULL) 99 * @param hello hello message for the peer (can be NULL)
101 * @param trust amount of trust we have in the peer
102 */ 100 */
103typedef void 101typedef void
104 (*GNUNET_PEERINFO_Processor) (void *cls, 102 (*GNUNET_PEERINFO_Processor) (void *cls,
105 const struct GNUNET_PeerIdentity * peer, 103 const struct GNUNET_PeerIdentity * peer,
106 const struct GNUNET_HELLO_Message * hello, 104 const struct GNUNET_HELLO_Message * hello);
107 uint32_t trust);
108 105
109 106
110/** 107/**
@@ -123,12 +120,11 @@ struct GNUNET_PEERINFO_IteratorContext;
123 * being done; however, the trust argument will be set to zero if we 120 * being done; however, the trust argument will be set to zero if we
124 * are done, 1 if we timed out and 2 for fatal error. 121 * are done, 1 if we timed out and 2 for fatal error.
125 * 122 *
126 * Instead of calling this function with 'peer == NULL' and 'trust == 123 * Instead of calling this function with 'peer == NULL'
127 * 0', it is often better to use 'GNUNET_PEERINFO_notify'. 124 * it is often better to use 'GNUNET_PEERINFO_notify'.
128 * 125 *
129 * @param h handle to the peerinfo service 126 * @param h handle to the peerinfo service
130 * @param peer restrict iteration to this peer only (can be NULL) 127 * @param peer restrict iteration to this peer only (can be NULL)
131 * @param trust_delta how much to change the trust in all matching peers
132 * @param timeout how long to wait until timing out 128 * @param timeout how long to wait until timing out
133 * @param callback the method to call for each peer 129 * @param callback the method to call for each peer
134 * @param callback_cls closure for callback 130 * @param callback_cls closure for callback
@@ -138,7 +134,6 @@ struct GNUNET_PEERINFO_IteratorContext;
138struct GNUNET_PEERINFO_IteratorContext * 134struct GNUNET_PEERINFO_IteratorContext *
139GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h, 135GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
140 const struct GNUNET_PeerIdentity *peer, 136 const struct GNUNET_PeerIdentity *peer,
141 int trust_delta,
142 struct GNUNET_TIME_Relative timeout, 137 struct GNUNET_TIME_Relative timeout,
143 GNUNET_PEERINFO_Processor callback, 138 GNUNET_PEERINFO_Processor callback,
144 void *callback_cls); 139 void *callback_cls);
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index bfa1314c9..8a1df7ff9 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -52,26 +52,6 @@ extern "C"
52#define GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE 3 52#define GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE 3
53 53
54 54
55/**
56 * Set a statistical value.
57 */
58#define GNUNET_MESSAGE_TYPE_STATISTICS_SET 4
59
60/**
61 * Get a statistical value(s).
62 */
63#define GNUNET_MESSAGE_TYPE_STATISTICS_GET 5
64
65/**
66 * Response to a STATISTICS_GET message (with value).
67 */
68#define GNUNET_MESSAGE_TYPE_STATISTICS_VALUE 6
69
70/**
71 * Response to a STATISTICS_GET message (end of value stream).
72 */
73#define GNUNET_MESSAGE_TYPE_STATISTICS_END 7
74
75 55
76/** 56/**
77 * Request to ARM to start a service. 57 * Request to ARM to start a service.
@@ -345,35 +325,40 @@ extern "C"
345#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT 68 325#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT 68
346 326
347/** 327/**
328 * Notify clients about peer status change.
329 */
330#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE 69
331
332/**
348 * Notify clients about incoming P2P messages. 333 * Notify clients about incoming P2P messages.
349 */ 334 */
350#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 69 335#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 70
351 336
352/** 337/**
353 * Notify clients about outgoing P2P transmissions. 338 * Notify clients about outgoing P2P transmissions.
354 */ 339 */
355#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND 70 340#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND 71
356 341
357/** 342/**
358 * Request from client to "configure" P2P connection. 343 * Request from client to "configure" P2P connection.
359 */ 344 */
360#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO 71 345#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO 72
361 346
362/** 347/**
363 * Response from server about (possibly updated) P2P 348 * Response from server about (possibly updated) P2P
364 * connection configuration. 349 * connection configuration.
365 */ 350 */
366#define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 72 351#define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 73
367 352
368/** 353/**
369 * Request from client with message to transmit. 354 * Request from client with message to transmit.
370 */ 355 */
371#define GNUNET_MESSAGE_TYPE_CORE_SEND 73 356#define GNUNET_MESSAGE_TYPE_CORE_SEND 74
372 357
373/** 358/**
374 * Request from client asking to connect to a peer. 359 * Request from client asking to connect to a peer.
375 */ 360 */
376#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 74 361#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 75
377 362
378 363
379/** 364/**
@@ -584,6 +569,39 @@ extern "C"
584 */ 569 */
585#define GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT 160 570#define GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT 160
586 571
572
573/**
574 * Set a statistical value.
575 */
576#define GNUNET_MESSAGE_TYPE_STATISTICS_SET 168
577
578/**
579 * Get a statistical value(s).
580 */
581#define GNUNET_MESSAGE_TYPE_STATISTICS_GET 169
582
583/**
584 * Response to a STATISTICS_GET message (with value).
585 */
586#define GNUNET_MESSAGE_TYPE_STATISTICS_VALUE 170
587
588/**
589 * Response to a STATISTICS_GET message (end of value stream).
590 */
591#define GNUNET_MESSAGE_TYPE_STATISTICS_END 171
592
593/**
594 * Watch changes to a statistical value. Message format is the same
595 * as for GET, except that the subsystem and entry name must be given.
596 */
597#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH 172
598
599/**
600 * Changes to a watched value.
601 */
602#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE 173
603
604
587/** 605/**
588 * Type used to match 'all' message types. 606 * Type used to match 'all' message types.
589 */ 607 */
diff --git a/src/include/gnunet_statistics_service.h b/src/include/gnunet_statistics_service.h
index 5c166d43d..71c834f2a 100644
--- a/src/include/gnunet_statistics_service.h
+++ b/src/include/gnunet_statistics_service.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -94,6 +94,26 @@ void GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h,
94 94
95 95
96/** 96/**
97 * Watch statistics from the peer (be notified whenever they change).
98 * Note that the only way to cancel a "watch" request is to destroy
99 * the statistics handle given as the first argument to this call.
100 *
101 * @param handle identification of the statistics service
102 * @param subsystem limit to the specified subsystem, never NULL
103 * @param name name of the statistic value, never NULL
104 * @param proc function to call on each value
105 * @param proc_cls closure for proc
106 * @return GNUNET_OK on success, GNUNET_SYSERR on error
107 */
108int
109GNUNET_STATISTICS_watch (struct GNUNET_STATISTICS_Handle *handle,
110 const char *subsystem,
111 const char *name,
112 GNUNET_STATISTICS_Iterator proc,
113 void *proc_cls);
114
115
116/**
97 * Continuation called by the "get_all" and "get" functions. 117 * Continuation called by the "get_all" and "get" functions.
98 * 118 *
99 * @param cls closure 119 * @param cls closure
diff --git a/src/peerinfo-tool/gnunet-peerinfo.c b/src/peerinfo-tool/gnunet-peerinfo.c
index 88bca1e7d..28f2284ce 100644
--- a/src/peerinfo-tool/gnunet-peerinfo.c
+++ b/src/peerinfo-tool/gnunet-peerinfo.c
@@ -49,7 +49,6 @@ struct PrintContext
49 char **address_list; 49 char **address_list;
50 unsigned int num_addresses; 50 unsigned int num_addresses;
51 uint32_t off; 51 uint32_t off;
52 uint32_t trust;
53}; 52};
54 53
55 54
@@ -60,9 +59,8 @@ dump_pc (struct PrintContext *pc)
60 unsigned int i; 59 unsigned int i;
61 60
62 GNUNET_CRYPTO_hash_to_enc (&pc->peer.hashPubKey, &enc); 61 GNUNET_CRYPTO_hash_to_enc (&pc->peer.hashPubKey, &enc);
63 printf (_("Peer `%s' with trust %8u\n"), 62 printf (_("Peer `%s'\n"),
64 (const char *) &enc, 63 (const char *) &enc);
65 pc->trust);
66 for (i=0;i<pc->num_addresses;i++) 64 for (i=0;i<pc->num_addresses;i++)
67 { 65 {
68 printf ("\t%s\n", 66 printf ("\t%s\n",
@@ -156,13 +154,13 @@ print_address (void *cls,
156 154
157/** 155/**
158 * Print information about the peer. 156 * Print information about the peer.
159 * Currently prints the GNUNET_PeerIdentity, trust and the IP. 157 * Currently prints the GNUNET_PeerIdentity and the IP.
160 * Could of course do more (e.g. resolve via DNS). 158 * Could of course do more (e.g. resolve via DNS).
161 */ 159 */
162static void 160static void
163print_peer_info (void *cls, 161print_peer_info (void *cls,
164 const struct GNUNET_PeerIdentity *peer, 162 const struct GNUNET_PeerIdentity *peer,
165 const struct GNUNET_HELLO_Message *hello, uint32_t trust) 163 const struct GNUNET_HELLO_Message *hello)
166{ 164{
167 struct GNUNET_CRYPTO_HashAsciiEncoded enc; 165 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
168 struct PrintContext *pc; 166 struct PrintContext *pc;
@@ -170,22 +168,8 @@ print_peer_info (void *cls,
170 if (peer == NULL) 168 if (peer == NULL)
171 { 169 {
172 GNUNET_PEERINFO_disconnect (peerinfo); 170 GNUNET_PEERINFO_disconnect (peerinfo);
173 switch (trust) 171 fprintf (stderr,
174 { 172 _("Error in communication with PEERINFO service\n"));
175 case 0:
176 break;
177 case 1:
178 fprintf (stderr,
179 _("Timeout trying to interact with PEERINFO service\n"));
180 break;
181 case 2:
182 fprintf (stderr,
183 _("Error in communication with PEERINFO service\n"));
184 break;
185 default:
186 GNUNET_break (0);
187 break;
188 }
189 return; 173 return;
190 } 174 }
191 if (be_quiet) 175 if (be_quiet)
@@ -196,7 +180,6 @@ print_peer_info (void *cls,
196 } 180 }
197 pc = GNUNET_malloc (sizeof (struct PrintContext)); 181 pc = GNUNET_malloc (sizeof (struct PrintContext));
198 pc->peer = *peer; 182 pc->peer = *peer;
199 pc->trust = trust;
200 GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &count_address, pc); 183 GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &count_address, pc);
201 if (0 == pc->off) 184 if (0 == pc->off)
202 { 185 {
@@ -228,27 +211,10 @@ run (void *cls,
228 struct GNUNET_PeerIdentity pid; 211 struct GNUNET_PeerIdentity pid;
229 struct GNUNET_CRYPTO_HashAsciiEncoded enc; 212 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
230 char *fn; 213 char *fn;
231 int delta;
232 214
233 sched = s; 215 sched = s;
234 cfg = c; 216 cfg = c;
235 delta = 0; 217 if (args[0] != NULL)
236 if ( (args[0] != NULL) &&
237 (args[1] != NULL) &&
238 (1 == sscanf(args[0], "%d", &delta)) &&
239 (GNUNET_OK ==
240 GNUNET_CRYPTO_hash_from_string (args[1],
241 &pid.hashPubKey)) )
242 {
243 peerinfo = GNUNET_PEERINFO_connect (sched, cfg);
244 GNUNET_PEERINFO_iterate (peerinfo,
245 &pid,
246 delta,
247 GNUNET_TIME_UNIT_SECONDS,
248 &print_peer_info, NULL);
249 return;
250 }
251 else if (args[0] != NULL)
252 { 218 {
253 fprintf (stderr, 219 fprintf (stderr,
254 _("Invalid command line argument `%s'\n"), 220 _("Invalid command line argument `%s'\n"),
@@ -266,7 +232,6 @@ run (void *cls,
266 } 232 }
267 (void) GNUNET_PEERINFO_iterate (peerinfo, 233 (void) GNUNET_PEERINFO_iterate (peerinfo,
268 NULL, 234 NULL,
269 0,
270 GNUNET_TIME_relative_multiply 235 GNUNET_TIME_relative_multiply
271 (GNUNET_TIME_UNIT_SECONDS, 2), 236 (GNUNET_TIME_UNIT_SECONDS, 2),
272 &print_peer_info, NULL); 237 &print_peer_info, NULL);
diff --git a/src/peerinfo-tool/test_gnunet_peerinfo.py.in b/src/peerinfo-tool/test_gnunet_peerinfo.py.in
index ba542f28a..01f76aa1e 100755
--- a/src/peerinfo-tool/test_gnunet_peerinfo.py.in
+++ b/src/peerinfo-tool/test_gnunet_peerinfo.py.in
@@ -46,12 +46,12 @@ try:
46 os.system ('gnunet-arm -q -i transport -c test_gnunet_peerinfo_data.conf') 46 os.system ('gnunet-arm -q -i transport -c test_gnunet_peerinfo_data.conf')
47 os.system ('sleep 1') 47 os.system ('sleep 1')
48 pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf') 48 pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf')
49 pinfo.expect (re.compile ("Peer `.*\' with trust *0\r")); 49 pinfo.expect (re.compile ("Peer `.*\'\r"));
50 pinfo.expect (re.compile (" *localhost:24357\r")); 50 pinfo.expect (re.compile (" *localhost:24357\r"));
51 pinfo.expect (pexpect.EOF); 51 pinfo.expect (pexpect.EOF);
52 52
53 pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf -n') 53 pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf -n')
54 pinfo.expect (re.compile ("Peer `.*\' with trust *0\r")); 54 pinfo.expect (re.compile ("Peer `.*\'\r"));
55 pinfo.expect (re.compile (" *127..*:24357\r")); 55 pinfo.expect (re.compile (" *127..*:24357\r"));
56 pinfo.expect (pexpect.EOF); 56 pinfo.expect (pexpect.EOF);
57 57
@@ -59,14 +59,6 @@ try:
59 pid = pinfo.read (-1) 59 pid = pinfo.read (-1)
60 pid = pid.strip () 60 pid = pid.strip ()
61 61
62 pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf 4 ' + pid)
63 pinfo.expect (re.compile ("Peer `" + pid + "\' with trust *4\r"));
64 pinfo.expect (pexpect.EOF);
65
66 pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf -- -4 ' + pid)
67 pinfo.expect (re.compile ("Peer `" + pid + "\' with trust *0\r"));
68 pinfo.expect (pexpect.EOF);
69
70finally: 62finally:
71 os.system ('gnunet-arm -c test_gnunet_peerinfo_data.conf -eq') 63 os.system ('gnunet-arm -c test_gnunet_peerinfo_data.conf -eq')
72 os.system ('rm -rf /tmp/gnunet-test-peerinfo/') 64 os.system ('rm -rf /tmp/gnunet-test-peerinfo/')
diff --git a/src/peerinfo/gnunet-service-peerinfo.c b/src/peerinfo/gnunet-service-peerinfo.c
index 692f71e9b..ee8749955 100644
--- a/src/peerinfo/gnunet-service-peerinfo.c
+++ b/src/peerinfo/gnunet-service-peerinfo.c
@@ -23,7 +23,7 @@
23 * @brief maintains list of known peers 23 * @brief maintains list of known peers
24 * 24 *
25 * Code to maintain the list of currently known hosts (in memory 25 * Code to maintain the list of currently known hosts (in memory
26 * structure of data/hosts/ and data/credit/). 26 * structure of data/hosts/).
27 * 27 *
28 * @author Christian Grothoff 28 * @author Christian Grothoff
29 * 29 *
@@ -46,11 +46,6 @@
46#define DATA_HOST_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) 46#define DATA_HOST_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
47 47
48/** 48/**
49 * How often do we flush trust values to disk?
50 */
51#define TRUST_FLUSH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
52
53/**
54 * How often do we discard old entries in data/hosts/? 49 * How often do we discard old entries in data/hosts/?
55 */ 50 */
56#define DATA_HOST_CLEAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60) 51#define DATA_HOST_CLEAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60)
@@ -76,16 +71,6 @@ struct HostEntry
76 */ 71 */
77 struct GNUNET_HELLO_Message *hello; 72 struct GNUNET_HELLO_Message *hello;
78 73
79 /**
80 * Trust rating for this peer
81 */
82 uint32_t trust;
83
84 /**
85 * Trust rating for this peer on disk.
86 */
87 uint32_t disk_trust;
88
89}; 74};
90 75
91 76
@@ -105,11 +90,6 @@ static struct GNUNET_SERVER_NotificationContext *notify_list;
105static char *networkIdDirectory; 90static char *networkIdDirectory;
106 91
107/** 92/**
108 * Where do we store trust information?
109 */
110static char *trustDirectory;
111
112/**
113 * Handle for reporting statistics. 93 * Handle for reporting statistics.
114 */ 94 */
115static struct GNUNET_STATISTICS_Handle *stats; 95static struct GNUNET_STATISTICS_Handle *stats;
@@ -129,7 +109,6 @@ make_info_message (const struct HostEntry *he)
129 im = GNUNET_malloc (sizeof (struct InfoMessage) + hs); 109 im = GNUNET_malloc (sizeof (struct InfoMessage) + hs);
130 im->header.size = htons (hs + sizeof (struct InfoMessage)); 110 im->header.size = htons (hs + sizeof (struct InfoMessage));
131 im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO); 111 im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
132 im->trust = htonl (he->trust);
133 im->peer = he->identity; 112 im->peer = he->identity;
134 if (he->hello != NULL) 113 if (he->hello != NULL)
135 memcpy (&im[1], he->hello, hs); 114 memcpy (&im[1], he->hello, hs);
@@ -184,25 +163,7 @@ get_host_filename (const struct GNUNET_PeerIdentity *id)
184 163
185 164
186/** 165/**
187 * Get the filename under which we would store the GNUNET_HELLO_Message 166 * Find the host entry for the given peer. FIXME: replace by hash map!
188 * for the given host and protocol.
189 * @return filename of the form DIRECTORY/HOSTID
190 */
191static char *
192get_trust_filename (const struct GNUNET_PeerIdentity *id)
193{
194 struct GNUNET_CRYPTO_HashAsciiEncoded fil;
195 char *fn;
196
197 GNUNET_CRYPTO_hash_to_enc (&id->hashPubKey, &fil);
198 GNUNET_asprintf (&fn, "%s%s%s", trustDirectory, DIR_SEPARATOR_STR, &fil);
199 return fn;
200}
201
202
203/**
204 * Find the host entry for the given peer. Call
205 * only when synchronized!
206 * @return NULL if not found 167 * @return NULL if not found
207 */ 168 */
208static struct HostEntry * 169static struct HostEntry *
@@ -247,13 +208,12 @@ static void
247add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity) 208add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
248{ 209{
249 struct HostEntry *entry; 210 struct HostEntry *entry;
250 char *fn;
251 uint32_t trust;
252 char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; 211 char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
253 const struct GNUNET_HELLO_Message *hello; 212 const struct GNUNET_HELLO_Message *hello;
254 struct GNUNET_HELLO_Message *hello_clean; 213 struct GNUNET_HELLO_Message *hello_clean;
255 int size; 214 int size;
256 struct GNUNET_TIME_Absolute now; 215 struct GNUNET_TIME_Absolute now;
216 char *fn;
257 217
258 entry = lookup_host_entry (identity); 218 entry = lookup_host_entry (identity);
259 if (entry != NULL) 219 if (entry != NULL)
@@ -264,11 +224,6 @@ add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
264 GNUNET_NO); 224 GNUNET_NO);
265 entry = GNUNET_malloc (sizeof (struct HostEntry)); 225 entry = GNUNET_malloc (sizeof (struct HostEntry));
266 entry->identity = *identity; 226 entry->identity = *identity;
267 fn = get_trust_filename (identity);
268 if ((GNUNET_DISK_file_test (fn) == GNUNET_YES) &&
269 (sizeof (trust) == GNUNET_DISK_fn_read (fn, &trust, sizeof (trust))))
270 entry->disk_trust = entry->trust = ntohl (trust);
271 GNUNET_free (fn);
272 227
273 fn = get_host_filename (identity); 228 fn = get_host_filename (identity);
274 if (GNUNET_DISK_file_test (fn) == GNUNET_YES) 229 if (GNUNET_DISK_file_test (fn) == GNUNET_YES)
@@ -302,56 +257,6 @@ add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
302 257
303 258
304/** 259/**
305 * Increase the host credit by a value.
306 *
307 * @param hostId is the identity of the host
308 * @param value is the int value by which the
309 * host credit is to be increased or decreased
310 * @returns the actual change in trust (positive or negative)
311 */
312static int
313change_host_trust (const struct GNUNET_PeerIdentity *hostId, int value)
314{
315 struct HostEntry *host;
316 unsigned int old_trust;
317
318 if (value == 0)
319 return 0;
320 host = lookup_host_entry (hostId);
321 if (host == NULL)
322 {
323 add_host_to_known_hosts (hostId);
324 host = lookup_host_entry (hostId);
325 }
326 GNUNET_assert (host != NULL);
327 old_trust = host->trust;
328 if (value > 0)
329 {
330 if (host->trust + value < host->trust)
331 {
332 value = UINT32_MAX - host->trust;
333 host->trust = UINT32_MAX;
334 }
335 else
336 host->trust += value;
337 }
338 else
339 {
340 if (host->trust < -value)
341 {
342 value = -host->trust;
343 host->trust = 0;
344 }
345 else
346 host->trust += value;
347 }
348 if (host->trust != old_trust)
349 notify_all (host);
350 return value;
351}
352
353
354/**
355 * Remove a file that should not be there. LOG 260 * Remove a file that should not be there. LOG
356 * success or failure. 261 * success or failure.
357 */ 262 */
@@ -480,16 +385,14 @@ bind_address (const struct GNUNET_PeerIdentity *peer,
480 385
481/** 386/**
482 * Do transmit info either for only the host matching the given 387 * Do transmit info either for only the host matching the given
483 * argument or for all known hosts and change their trust values by 388 * argument or for all known hosts.
484 * the given delta.
485 * 389 *
486 * @param only NULL to hit all hosts, otherwise specifies a particular target 390 * @param only NULL to hit all hosts, otherwise specifies a particular target
487 * @param trust_change how much should the trust be changed
488 * @param client who is making the request (and will thus receive our confirmation) 391 * @param client who is making the request (and will thus receive our confirmation)
489 */ 392 */
490static void 393static void
491send_to_each_host (const struct GNUNET_PeerIdentity *only, 394send_to_each_host (const struct GNUNET_PeerIdentity *only,
492 int trust_change, struct GNUNET_SERVER_Client *client) 395 struct GNUNET_SERVER_Client *client)
493{ 396{
494 struct HostEntry *pos; 397 struct HostEntry *pos;
495 struct InfoMessage *im; 398 struct InfoMessage *im;
@@ -508,7 +411,6 @@ send_to_each_host (const struct GNUNET_PeerIdentity *only,
508 memcmp (only, &pos->identity, 411 memcmp (only, &pos->identity,
509 sizeof (struct GNUNET_PeerIdentity)))) 412 sizeof (struct GNUNET_PeerIdentity))))
510 { 413 {
511 change_host_trust (&pos->identity, trust_change);
512 hs = 0; 414 hs = 0;
513 im = (struct InfoMessage *) buf; 415 im = (struct InfoMessage *) buf;
514 if (pos->hello != NULL) 416 if (pos->hello != NULL)
@@ -522,7 +424,7 @@ send_to_each_host (const struct GNUNET_PeerIdentity *only,
522 } 424 }
523 im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO); 425 im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
524 im->header.size = htons (sizeof (struct InfoMessage) + hs); 426 im->header.size = htons (sizeof (struct InfoMessage) + hs);
525 im->trust = htonl (pos->trust); 427 im->reserved = htonl (0);
526 im->peer = pos->identity; 428 im->peer = pos->identity;
527 GNUNET_SERVER_transmit_context_append_message (tc, 429 GNUNET_SERVER_transmit_context_append_message (tc,
528 &im->header); 430 &im->header);
@@ -542,58 +444,6 @@ send_to_each_host (const struct GNUNET_PeerIdentity *only,
542 444
543 445
544/** 446/**
545 * Write host-trust information to a file - flush the buffer entry!
546 * Assumes synchronized access.
547 */
548static void
549flush_trust (struct HostEntry *host)
550{
551 char *fn;
552 uint32_t trust;
553
554 if (host->trust == host->disk_trust)
555 return; /* unchanged */
556 fn = get_trust_filename (&host->identity);
557 if (host->trust == 0)
558 {
559 if ((0 != UNLINK (fn)) && (errno != ENOENT))
560 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
561 GNUNET_ERROR_TYPE_BULK, "unlink", fn);
562 }
563 else
564 {
565 trust = htonl (host->trust);
566 if (sizeof(uint32_t) == GNUNET_DISK_fn_write (fn, &trust,
567 sizeof(uint32_t),
568 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE
569 | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ))
570 host->disk_trust = host->trust;
571 }
572 GNUNET_free (fn);
573}
574
575/**
576 * Call this method periodically to scan data/hosts for new hosts.
577 */
578static void
579cron_flush_trust (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
580{
581 struct HostEntry *pos;
582
583 pos = hosts;
584 while (pos != NULL)
585 {
586 flush_trust (pos);
587 pos = pos->next;
588 }
589 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
590 return;
591 GNUNET_SCHEDULER_add_delayed (tc->sched,
592 TRUST_FLUSH_FREQ, &cron_flush_trust, NULL);
593}
594
595
596/**
597 * @brief delete expired HELLO entries in data/hosts/ 447 * @brief delete expired HELLO entries in data/hosts/
598 */ 448 */
599static int 449static int
@@ -711,7 +561,7 @@ handle_get (void *cls,
711 "GET", 561 "GET",
712 GNUNET_i2s (&lpm->peer)); 562 GNUNET_i2s (&lpm->peer));
713#endif 563#endif
714 send_to_each_host (&lpm->peer, ntohl (lpm->trust_change), client); 564 send_to_each_host (&lpm->peer, client);
715} 565}
716 566
717 567
@@ -727,15 +577,12 @@ handle_get_all (void *cls,
727 struct GNUNET_SERVER_Client *client, 577 struct GNUNET_SERVER_Client *client,
728 const struct GNUNET_MessageHeader *message) 578 const struct GNUNET_MessageHeader *message)
729{ 579{
730 const struct ListAllPeersMessage *lpm;
731
732 lpm = (const struct ListAllPeersMessage *) message;
733#if DEBUG_PEERINFO 580#if DEBUG_PEERINFO
734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
735 "`%s' message received\n", 582 "`%s' message received\n",
736 "GET_ALL"); 583 "GET_ALL");
737#endif 584#endif
738 send_to_each_host (NULL, ntohl (lpm->trust_change), client); 585 send_to_each_host (NULL, client);
739} 586}
740 587
741 588
@@ -814,7 +661,7 @@ run (void *cls,
814 {&handle_get, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET, 661 {&handle_get, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET,
815 sizeof (struct ListPeerMessage)}, 662 sizeof (struct ListPeerMessage)},
816 {&handle_get_all, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL, 663 {&handle_get_all, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL,
817 sizeof (struct ListAllPeersMessage)}, 664 sizeof (struct GNUNET_MessageHeader)},
818 {&handle_notify, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY, 665 {&handle_notify, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY,
819 sizeof (struct GNUNET_MessageHeader)}, 666 sizeof (struct GNUNET_MessageHeader)},
820 {NULL, NULL, 0, 0} 667 {NULL, NULL, 0, 0}
@@ -826,20 +673,11 @@ run (void *cls,
826 "peerinfo", 673 "peerinfo",
827 "HOSTS", 674 "HOSTS",
828 &networkIdDirectory)); 675 &networkIdDirectory));
829 GNUNET_assert (GNUNET_OK ==
830 GNUNET_CONFIGURATION_get_value_filename (cfg,
831 "peerinfo",
832 "TRUST",
833 &trustDirectory));
834 GNUNET_DISK_directory_create (networkIdDirectory); 676 GNUNET_DISK_directory_create (networkIdDirectory);
835 GNUNET_DISK_directory_create (trustDirectory);
836 GNUNET_SCHEDULER_add_with_priority (sched, 677 GNUNET_SCHEDULER_add_with_priority (sched,
837 GNUNET_SCHEDULER_PRIORITY_IDLE, 678 GNUNET_SCHEDULER_PRIORITY_IDLE,
838 &cron_scan_directory_data_hosts, NULL); 679 &cron_scan_directory_data_hosts, NULL);
839 GNUNET_SCHEDULER_add_with_priority (sched, 680 GNUNET_SCHEDULER_add_with_priority (sched,
840 GNUNET_SCHEDULER_PRIORITY_HIGH,
841 &cron_flush_trust, NULL);
842 GNUNET_SCHEDULER_add_with_priority (sched,
843 GNUNET_SCHEDULER_PRIORITY_IDLE, 681 GNUNET_SCHEDULER_PRIORITY_IDLE,
844 &cron_clean_data_hosts, NULL); 682 &cron_clean_data_hosts, NULL);
845 GNUNET_SCHEDULER_add_delayed (sched, 683 GNUNET_SCHEDULER_add_delayed (sched,
@@ -868,7 +706,6 @@ main (int argc, char *const *argv)
868 GNUNET_SERVICE_OPTION_NONE, 706 GNUNET_SERVICE_OPTION_NONE,
869 &run, NULL)) ? 0 : 1; 707 &run, NULL)) ? 0 : 1;
870 GNUNET_free_non_null (networkIdDirectory); 708 GNUNET_free_non_null (networkIdDirectory);
871 GNUNET_free_non_null (trustDirectory);
872 return ret; 709 return ret;
873} 710}
874 711
diff --git a/src/peerinfo/peerinfo.h b/src/peerinfo/peerinfo.h
index d8d645b13..87860097a 100644
--- a/src/peerinfo/peerinfo.h
+++ b/src/peerinfo/peerinfo.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -31,8 +31,7 @@
31 31
32/** 32/**
33 * Message requesting a listing of all known peers, 33 * Message requesting a listing of all known peers,
34 * possibly modified by the specified trust value 34 * possibly restricted to the specified peer identity.
35 * and restricted to the specified peer identity.
36 */ 35 */
37struct ListPeerMessage 36struct ListPeerMessage
38{ 37{
@@ -43,10 +42,9 @@ struct ListPeerMessage
43 struct GNUNET_MessageHeader header; 42 struct GNUNET_MessageHeader header;
44 43
45 /** 44 /**
46 * How much to change the trust in each returned peer, 45 * Always zero.
47 * in network byte order.
48 */ 46 */
49 int32_t trust_change GNUNET_PACKED; 47 uint32_t reserved GNUNET_PACKED;
50 48
51 /** 49 /**
52 * Restrict to peers with this identity (optional 50 * Restrict to peers with this identity (optional
@@ -58,28 +56,6 @@ struct ListPeerMessage
58 56
59 57
60/** 58/**
61 * Message requesting a listing of all known peers,
62 * possibly modified by the specified trust value
63 * and restricted to the specified peer identity.
64 */
65struct ListAllPeersMessage
66{
67
68 /**
69 * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_GET
70 */
71 struct GNUNET_MessageHeader header;
72
73 /**
74 * How much to change the trust in each returned peer,
75 * in network byte order.
76 */
77 int32_t trust_change GNUNET_PACKED;
78
79};
80
81
82/**
83 * Message used to inform the client about 59 * Message used to inform the client about
84 * a particular peer; this message is optionally followed 60 * a particular peer; this message is optionally followed
85 * by a HELLO message for the respective peer (if available). 61 * by a HELLO message for the respective peer (if available).
@@ -95,10 +71,9 @@ struct InfoMessage
95 struct GNUNET_MessageHeader header; 71 struct GNUNET_MessageHeader header;
96 72
97 /** 73 /**
98 * Amount of trust we now have in the peer, 74 * Always zero.
99 * in network byte order.
100 */ 75 */
101 uint32_t trust GNUNET_PACKED; 76 uint32_t reserved GNUNET_PACKED;
102 77
103 /** 78 /**
104 * About which peer are we talking here? 79 * About which peer are we talking here?
diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c
index a1eeeb220..1f382f096 100644
--- a/src/peerinfo/peerinfo_api.c
+++ b/src/peerinfo/peerinfo_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2001, 2002, 2004, 2005, 2007, 2009 Christian Grothoff (and other contributing authors) 3 (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -397,7 +397,7 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
397 GNUNET_SCHEDULER_cancel (ic->h->sched, 397 GNUNET_SCHEDULER_cancel (ic->h->sched,
398 ic->timeout_task); 398 ic->timeout_task);
399 if (ic->callback != NULL) 399 if (ic->callback != NULL)
400 ic->callback (ic->callback_cls, NULL, NULL, 1); 400 ic->callback (ic->callback_cls, NULL, NULL);
401 GNUNET_free (ic); 401 GNUNET_free (ic);
402 return; 402 return;
403 } 403 }
@@ -413,7 +413,7 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
413 GNUNET_SCHEDULER_cancel (ic->h->sched, 413 GNUNET_SCHEDULER_cancel (ic->h->sched,
414 ic->timeout_task); 414 ic->timeout_task);
415 if (ic->callback != NULL) 415 if (ic->callback != NULL)
416 ic->callback (ic->callback_cls, NULL, NULL, 0); 416 ic->callback (ic->callback_cls, NULL, NULL);
417 GNUNET_free (ic); 417 GNUNET_free (ic);
418 return; 418 return;
419 } 419 }
@@ -428,7 +428,7 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
428 GNUNET_SCHEDULER_cancel (ic->h->sched, 428 GNUNET_SCHEDULER_cancel (ic->h->sched,
429 ic->timeout_task); 429 ic->timeout_task);
430 if (ic->callback != NULL) 430 if (ic->callback != NULL)
431 ic->callback (ic->callback_cls, NULL, NULL, 2); 431 ic->callback (ic->callback_cls, NULL, NULL);
432 GNUNET_free (ic); 432 GNUNET_free (ic);
433 return; 433 return;
434 } 434 }
@@ -446,7 +446,7 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
446 GNUNET_SCHEDULER_cancel (ic->h->sched, 446 GNUNET_SCHEDULER_cancel (ic->h->sched,
447 ic->timeout_task); 447 ic->timeout_task);
448 if (ic->callback != NULL) 448 if (ic->callback != NULL)
449 ic->callback (ic->callback_cls, NULL, NULL, 2); 449 ic->callback (ic->callback_cls, NULL, NULL);
450 GNUNET_free (ic); 450 GNUNET_free (ic);
451 return; 451 return;
452 } 452 }
@@ -461,7 +461,7 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
461#endif 461#endif
462 ic->h->in_receive = GNUNET_YES; 462 ic->h->in_receive = GNUNET_YES;
463 if (ic->callback != NULL) 463 if (ic->callback != NULL)
464 ic->callback (ic->callback_cls, &im->peer, hello, ntohl (im->trust)); 464 ic->callback (ic->callback_cls, &im->peer, hello);
465 GNUNET_CLIENT_receive (ic->h->client, 465 GNUNET_CLIENT_receive (ic->h->client,
466 &peerinfo_handler, 466 &peerinfo_handler,
467 ic, 467 ic,
@@ -497,7 +497,7 @@ iterator_start_receive (void *cls,
497 reconnect (ic->h); 497 reconnect (ic->h);
498 trigger_transmit (ic->h); 498 trigger_transmit (ic->h);
499 if (ic->callback != NULL) 499 if (ic->callback != NULL)
500 ic->callback (ic->callback_cls, NULL, NULL, 1); 500 ic->callback (ic->callback_cls, NULL, NULL);
501 GNUNET_free (ic); 501 GNUNET_free (ic);
502 return; 502 return;
503 } 503 }
@@ -536,7 +536,7 @@ signal_timeout (void *cls,
536 GNUNET_CONTAINER_DLL_remove (ic->h->tq_head, 536 GNUNET_CONTAINER_DLL_remove (ic->h->tq_head,
537 ic->h->tq_tail, 537 ic->h->tq_tail,
538 ic->tqe); 538 ic->tqe);
539 ic->callback (ic->callback_cls, NULL, NULL, 1); 539 ic->callback (ic->callback_cls, NULL, NULL);
540 ic->callback = NULL; 540 ic->callback = NULL;
541 if (ic->in_receive) 541 if (ic->in_receive)
542 return; 542 return;
@@ -551,16 +551,11 @@ signal_timeout (void *cls,
551 * host and then finally once with a NULL pointer. After that final 551 * host and then finally once with a NULL pointer. After that final
552 * invocation, the iterator context must no longer be used. 552 * invocation, the iterator context must no longer be used.
553 * 553 *
554 * Note that the last call can be triggered by timeout or by simply 554 * Instead of calling this function with 'peer == NULL' it is often
555 * being done; however, the trust argument will be set to zero if we 555 * better to use 'GNUNET_PEERINFO_notify'.
556 * are done, 1 if we timed out and 2 for fatal error.
557 *
558 * Instead of calling this function with 'peer == NULL' and 'trust ==
559 * 0', it is often better to use 'GNUNET_PEERINFO_notify'.
560 * 556 *
561 * @param h handle to the peerinfo service 557 * @param h handle to the peerinfo service
562 * @param peer restrict iteration to this peer only (can be NULL) 558 * @param peer restrict iteration to this peer only (can be NULL)
563 * @param trust_delta how much to change the trust in all matching peers
564 * @param timeout how long to wait until timing out 559 * @param timeout how long to wait until timing out
565 * @param callback the method to call for each peer 560 * @param callback the method to call for each peer
566 * @param callback_cls closure for callback 561 * @param callback_cls closure for callback
@@ -570,12 +565,11 @@ signal_timeout (void *cls,
570struct GNUNET_PEERINFO_IteratorContext * 565struct GNUNET_PEERINFO_IteratorContext *
571GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h, 566GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
572 const struct GNUNET_PeerIdentity *peer, 567 const struct GNUNET_PeerIdentity *peer,
573 int trust_delta,
574 struct GNUNET_TIME_Relative timeout, 568 struct GNUNET_TIME_Relative timeout,
575 GNUNET_PEERINFO_Processor callback, 569 GNUNET_PEERINFO_Processor callback,
576 void *callback_cls) 570 void *callback_cls)
577{ 571{
578 struct ListAllPeersMessage *lapm; 572 struct GNUNET_MessageHeader *lapm;
579 struct ListPeerMessage *lpm; 573 struct ListPeerMessage *lpm;
580 struct GNUNET_PEERINFO_IteratorContext *ic; 574 struct GNUNET_PEERINFO_IteratorContext *ic;
581 struct TransmissionQueueEntry *tqe; 575 struct TransmissionQueueEntry *tqe;
@@ -587,12 +581,11 @@ GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
587 "Requesting list of peers from PEERINFO service\n"); 581 "Requesting list of peers from PEERINFO service\n");
588#endif 582#endif
589 tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) + 583 tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) +
590 sizeof (struct ListAllPeersMessage)); 584 sizeof (struct GNUNET_MessageHeader));
591 tqe->size = sizeof (struct ListAllPeersMessage); 585 tqe->size = sizeof (struct GNUNET_MessageHeader);
592 lapm = (struct ListAllPeersMessage *) &tqe[1]; 586 lapm = (struct GNUNET_MessageHeader *) &tqe[1];
593 lapm->header.size = htons (sizeof (struct ListAllPeersMessage)); 587 lapm->size = htons (sizeof (struct GNUNET_MessageHeader));
594 lapm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL); 588 lapm->type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
595 lapm->trust_change = htonl (trust_delta);
596 } 589 }
597 else 590 else
598 { 591 {
@@ -607,7 +600,6 @@ GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
607 lpm = (struct ListPeerMessage *) &tqe[1]; 600 lpm = (struct ListPeerMessage *) &tqe[1];
608 lpm->header.size = htons (sizeof (struct ListPeerMessage)); 601 lpm->header.size = htons (sizeof (struct ListPeerMessage));
609 lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET); 602 lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET);
610 lpm->trust_change = htonl (trust_delta);
611 memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity)); 603 memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity));
612 } 604 }
613 ic = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_IteratorContext)); 605 ic = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_IteratorContext));
diff --git a/src/peerinfo/peerinfo_api_notify.c b/src/peerinfo/peerinfo_api_notify.c
index 04e8baea0..c7a9c6145 100644
--- a/src/peerinfo/peerinfo_api_notify.c
+++ b/src/peerinfo/peerinfo_api_notify.c
@@ -142,7 +142,7 @@ process_notification (void *cls,
142 "Received information about peer `%s' from peerinfo database\n", 142 "Received information about peer `%s' from peerinfo database\n",
143 GNUNET_i2s (&im->peer)); 143 GNUNET_i2s (&im->peer));
144#endif 144#endif
145 nc->callback (nc->callback_cls, &im->peer, hello, ntohl (im->trust)); 145 nc->callback (nc->callback_cls, &im->peer, hello);
146 receive_notifications (nc); 146 receive_notifications (nc);
147} 147}
148 148
diff --git a/src/peerinfo/test_peerinfo_api.c b/src/peerinfo/test_peerinfo_api.c
index dd931f4bc..47304d549 100644
--- a/src/peerinfo/test_peerinfo_api.c
+++ b/src/peerinfo/test_peerinfo_api.c
@@ -102,7 +102,7 @@ add_peer ()
102static void 102static void
103process (void *cls, 103process (void *cls,
104 const struct GNUNET_PeerIdentity *peer, 104 const struct GNUNET_PeerIdentity *peer,
105 const struct GNUNET_HELLO_Message *hello, uint32_t trust) 105 const struct GNUNET_HELLO_Message *hello)
106{ 106{
107 int *ok = cls; 107 int *ok = cls;
108 unsigned int agc; 108 unsigned int agc;
@@ -118,7 +118,6 @@ process (void *cls,
118 add_peer (); 118 add_peer ();
119 ic = GNUNET_PEERINFO_iterate (h, 119 ic = GNUNET_PEERINFO_iterate (h,
120 NULL, 120 NULL,
121 0,
122 GNUNET_TIME_relative_multiply 121 GNUNET_TIME_relative_multiply
123 (GNUNET_TIME_UNIT_SECONDS, 15), 122 (GNUNET_TIME_UNIT_SECONDS, 15),
124 &process, cls); 123 &process, cls);
@@ -126,7 +125,6 @@ process (void *cls,
126 } 125 }
127 GNUNET_assert (peer == NULL); 126 GNUNET_assert (peer == NULL);
128 GNUNET_assert (2 == *ok); 127 GNUNET_assert (2 == *ok);
129 GNUNET_assert (trust == 0);
130 GNUNET_PEERINFO_disconnect (h); 128 GNUNET_PEERINFO_disconnect (h);
131 h = NULL; 129 h = NULL;
132 *ok = 0; 130 *ok = 0;
@@ -156,7 +154,6 @@ run (void *cls,
156 add_peer (); 154 add_peer ();
157 ic = GNUNET_PEERINFO_iterate (h, 155 ic = GNUNET_PEERINFO_iterate (h,
158 NULL, 156 NULL,
159 0,
160 GNUNET_TIME_relative_multiply 157 GNUNET_TIME_relative_multiply
161 (GNUNET_TIME_UNIT_SECONDS, 15), 158 (GNUNET_TIME_UNIT_SECONDS, 15),
162 &process, cls); 159 &process, cls);
diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c
index 3ff751efe..251302a66 100644
--- a/src/statistics/gnunet-service-statistics.c
+++ b/src/statistics/gnunet-service-statistics.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -27,6 +27,7 @@
27 * - use BIO for IO operations 27 * - use BIO for IO operations
28 */ 28 */
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_container_lib.h"
30#include "gnunet_disk_lib.h" 31#include "gnunet_disk_lib.h"
31#include "gnunet_getopt_lib.h" 32#include "gnunet_getopt_lib.h"
32#include "gnunet_protocols.h" 33#include "gnunet_protocols.h"
@@ -37,6 +38,41 @@
37#include "statistics.h" 38#include "statistics.h"
38 39
39/** 40/**
41 * Watch entry.
42 */
43struct WatchEntry
44{
45
46 struct WatchEntry *next;
47
48 struct WatchEntry *prev;
49
50 struct GNUNET_SERVER_Client *client;
51
52 uint64_t last_value;
53
54 uint32_t wid;
55
56};
57
58
59/**
60 * Client entry.
61 */
62struct ClientEntry
63{
64
65 struct ClientEntry *next;
66
67 struct ClientEntry *prev;
68
69 struct GNUNET_SERVER_Client *client;
70
71 uint32_t max_wid;
72
73};
74
75/**
40 * Entry in the statistics list. 76 * Entry in the statistics list.
41 */ 77 */
42struct StatsEntry 78struct StatsEntry
@@ -66,6 +102,18 @@ struct StatsEntry
66 struct GNUNET_STATISTICS_SetMessage *msg; 102 struct GNUNET_STATISTICS_SetMessage *msg;
67 103
68 /** 104 /**
105 * Watch context for changes to this
106 * value, or NULL for none.
107 */
108 struct WatchEntry *we_head;
109
110 /**
111 * Watch context for changes to this
112 * value, or NULL for none.
113 */
114 struct WatchEntry *we_tail;
115
116 /**
69 * Our value. 117 * Our value.
70 */ 118 */
71 uint64_t value; 119 uint64_t value;
@@ -92,6 +140,21 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;
92 */ 140 */
93static struct StatsEntry *start; 141static struct StatsEntry *start;
94 142
143static struct ClientEntry *client_head;
144
145static struct ClientEntry *client_tail;
146
147/**
148 * Our notification context.
149 */
150static struct GNUNET_SERVER_NotificationContext *nc;
151
152/**
153 * Counter used to generate unique values.
154 */
155static uint32_t uidgen;
156
157
95/** 158/**
96 * Load persistent values from disk. Disk format is 159 * Load persistent values from disk. Disk format is
97 * exactly the same format that we also use for 160 * exactly the same format that we also use for
@@ -209,7 +272,7 @@ save ()
209 * Transmit the given stats value. 272 * Transmit the given stats value.
210 */ 273 */
211static void 274static void
212transmit (struct GNUNET_SERVER_TransmitContext *tc, 275transmit (struct GNUNET_SERVER_Client *client,
213 const struct StatsEntry *e) 276 const struct StatsEntry *e)
214{ 277{
215 struct GNUNET_STATISTICS_ReplyMessage *m; 278 struct GNUNET_STATISTICS_ReplyMessage *m;
@@ -232,10 +295,11 @@ transmit (struct GNUNET_SERVER_TransmitContext *tc,
232 2, e->service, e->name)); 295 2, e->service, e->name));
233#if DEBUG_STATISTICS 296#if DEBUG_STATISTICS
234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
235 "Transmitting value for `%s:%s': %llu\n", 298 "Transmitting value for `%s:%s' (%d): %llu\n",
236 e->service, e->name, e->value); 299 e->service, e->name,
300 e->persistent, e->value);
237#endif 301#endif
238 GNUNET_SERVER_transmit_context_append_message (tc, &m->header); 302 GNUNET_SERVER_notification_context_unicast (nc, client, &m->header, GNUNET_NO);
239 GNUNET_free (m); 303 GNUNET_free (m);
240} 304}
241 305
@@ -252,6 +316,32 @@ matches (const struct StatsEntry *e, const char *service, const char *name)
252} 316}
253 317
254 318
319static struct ClientEntry *
320make_client_entry (struct GNUNET_SERVER_Client *client)
321{
322 struct ClientEntry *ce;
323
324 if (client == NULL)
325 return NULL;
326 ce = client_head;
327 while (ce != NULL)
328 {
329 if (ce->client == client)
330 return ce;
331 ce = ce->next;
332 }
333 ce = GNUNET_malloc (sizeof (struct ClientEntry));
334 ce->client = client;
335 GNUNET_SERVER_client_keep (client);
336 GNUNET_CONTAINER_DLL_insert (client_head,
337 client_tail,
338 ce);
339 GNUNET_SERVER_notification_context_add (nc,
340 client);
341 return ce;
342}
343
344
255/** 345/**
256 * Handle GET-message. 346 * Handle GET-message.
257 * 347 *
@@ -266,12 +356,13 @@ handle_get (void *cls,
266 struct GNUNET_SERVER_Client *client, 356 struct GNUNET_SERVER_Client *client,
267 const struct GNUNET_MessageHeader *message) 357 const struct GNUNET_MessageHeader *message)
268{ 358{
359 struct GNUNET_MessageHeader end;
269 char *service; 360 char *service;
270 char *name; 361 char *name;
271 struct StatsEntry *pos; 362 struct StatsEntry *pos;
272 struct GNUNET_SERVER_TransmitContext *tc;
273 size_t size; 363 size_t size;
274 364
365 make_client_entry (client);
275 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); 366 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
276 if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], 367 if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
277 size, 2, &service, &name)) 368 size, 2, &service, &name))
@@ -285,20 +376,51 @@ handle_get (void *cls,
285 "Received request for statistics on `%s:%s'\n", 376 "Received request for statistics on `%s:%s'\n",
286 strlen (service) ? service : "*", strlen (name) ? name : "*"); 377 strlen (service) ? service : "*", strlen (name) ? name : "*");
287#endif 378#endif
288 tc = GNUNET_SERVER_transmit_context_create (client);
289 pos = start; 379 pos = start;
290 while (pos != NULL) 380 while (pos != NULL)
291 { 381 {
292 if (matches (pos, service, name)) 382 if (matches (pos, service, name))
293 transmit (tc, pos); 383 transmit (client, pos);
294 pos = pos->next; 384 pos = pos->next;
295 } 385 }
296 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, 386 end.size = htons (sizeof (struct GNUNET_MessageHeader));
297 GNUNET_MESSAGE_TYPE_STATISTICS_END); 387 end.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_END);
298 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); 388 GNUNET_SERVER_notification_context_unicast (nc,
389 client,
390 &end,
391 GNUNET_NO);
392 GNUNET_SERVER_receive_done (client,
393 GNUNET_OK);
299} 394}
300 395
301 396
397static void
398notify_change (struct StatsEntry *se)
399{
400 struct GNUNET_STATISTICS_WatchValueMessage wvm;
401 struct WatchEntry *pos;
402
403 pos = se->we_head;
404 while (pos != NULL)
405 {
406 if (pos->last_value != se->value)
407 {
408 wvm.header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE);
409 wvm.header.size = htons (sizeof (struct GNUNET_STATISTICS_WatchValueMessage));
410 wvm.flags = htonl (se->persistent ? GNUNET_STATISTICS_PERSIST_BIT : 0);
411 wvm.wid = htonl (pos->wid);
412 wvm.reserved = htonl (0);
413 wvm.value = GNUNET_htonll (se->value);
414 GNUNET_SERVER_notification_context_unicast (nc,
415 pos->client,
416 &wvm.header,
417 GNUNET_NO);
418 pos->last_value = se->value;
419 }
420 pos = pos->next;
421 }
422}
423
302/** 424/**
303 * Handle SET-message. 425 * Handle SET-message.
304 * 426 *
@@ -311,11 +433,6 @@ handle_set (void *cls,
311 struct GNUNET_SERVER_Client *client, 433 struct GNUNET_SERVER_Client *client,
312 const struct GNUNET_MessageHeader *message) 434 const struct GNUNET_MessageHeader *message)
313{ 435{
314 /**
315 * Counter used to generate unique values.
316 */
317 static uint32_t uidgen;
318
319 char *service; 436 char *service;
320 char *name; 437 char *name;
321 uint16_t msize; 438 uint16_t msize;
@@ -326,7 +443,9 @@ handle_set (void *cls,
326 uint32_t flags; 443 uint32_t flags;
327 uint64_t value; 444 uint64_t value;
328 int64_t delta; 445 int64_t delta;
446 int changed;
329 447
448 make_client_entry (client);
330 msize = ntohs (message->size); 449 msize = ntohs (message->size);
331 if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage)) 450 if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage))
332 { 451 {
@@ -344,13 +463,15 @@ handle_set (void *cls,
344 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 463 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
345 return; 464 return;
346 } 465 }
466 flags = ntohl (msg->flags);
467 value = GNUNET_ntohll (msg->value);
347#if DEBUG_STATISTICS 468#if DEBUG_STATISTICS
348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
349 "Received request to update statistic on `%s:%s'\n", 470 "Received request to update statistic on `%s:%s' (%u) to/by %llu\n",
350 service, name); 471 service, name,
472 (unsigned int) flags,
473 (unsigned long long) value);
351#endif 474#endif
352 flags = ntohl (msg->flags);
353 value = GNUNET_ntohll (msg->value);
354 pos = start; 475 pos = start;
355 prev = NULL; 476 prev = NULL;
356 while (pos != NULL) 477 while (pos != NULL)
@@ -359,17 +480,20 @@ handle_set (void *cls,
359 { 480 {
360 if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) 481 if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0)
361 { 482 {
483 changed = (pos->value != value);
362 pos->value = value; 484 pos->value = value;
363 } 485 }
364 else 486 else
365 { 487 {
366 delta = (int64_t) value; 488 delta = (int64_t) value;
367 if ((delta < 0) && (pos->value < -delta)) 489 if ((delta < 0) && (pos->value < -delta))
368 { 490 {
369 pos->value = 0; 491 changed = (pos->value != 0);
492 pos->value = 0;
370 } 493 }
371 else 494 else
372 { 495 {
496 changed = (delta != 0);
373 GNUNET_break ((delta <= 0) || 497 GNUNET_break ((delta <= 0) ||
374 (pos->value + delta > pos->value)); 498 (pos->value + delta > pos->value));
375 pos->value += delta; 499 pos->value += delta;
@@ -391,6 +515,8 @@ handle_set (void *cls,
391 "Statistic `%s:%s' updated to value %llu.\n", 515 "Statistic `%s:%s' updated to value %llu.\n",
392 service, name, pos->value); 516 service, name, pos->value);
393#endif 517#endif
518 if (changed)
519 notify_change (pos);
394 GNUNET_SERVER_receive_done (client, GNUNET_OK); 520 GNUNET_SERVER_receive_done (client, GNUNET_OK);
395 return; 521 return;
396 } 522 }
@@ -420,6 +546,86 @@ handle_set (void *cls,
420 546
421 547
422/** 548/**
549 * Handle WATCH-message.
550 *
551 * @param cls closure
552 * @param client identification of the client
553 * @param message the actual message
554 */
555static void
556handle_watch (void *cls,
557 struct GNUNET_SERVER_Client *client,
558 const struct GNUNET_MessageHeader *message)
559{
560 char *service;
561 char *name;
562 uint16_t msize;
563 uint16_t size;
564 struct StatsEntry *pos;
565 struct ClientEntry *ce;
566 struct WatchEntry *we;
567
568 ce = make_client_entry (client);
569 msize = ntohs (message->size);
570 if (msize < sizeof (struct GNUNET_MessageHeader))
571 {
572 GNUNET_break (0);
573 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
574 return;
575 }
576 size = msize - sizeof (struct GNUNET_MessageHeader);
577 if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
578 size, 2, &service, &name))
579 {
580 GNUNET_break (0);
581 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
582 return;
583 }
584#if DEBUG_STATISTICS
585 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
586 "Received request to watch statistic on `%s:%s'\n",
587 service, name);
588#endif
589 pos = start;
590 while (pos != NULL)
591 {
592 if (matches (pos, service, name))
593 break;
594 pos = pos->next;
595 }
596 if (pos == NULL)
597 {
598 pos = GNUNET_malloc (sizeof (struct StatsEntry) +
599 sizeof (struct GNUNET_STATISTICS_SetMessage) +
600 size);
601 pos->next = start;
602 pos->uid = uidgen++;
603 pos->msg = (void *) &pos[1];
604 pos->msg->header.size = htons (sizeof (struct GNUNET_STATISTICS_SetMessage) +
605 size);
606 pos->msg->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_SET);
607 memcpy (pos->msg, message, ntohs (message->size));
608 pos->service = (const char *) &pos->msg[1];
609 memcpy (&pos->msg[1], service, strlen (service)+1);
610 pos->name = &pos->service[strlen (pos->service) + 1];
611 memcpy ((void*) pos->name, name, strlen (name)+1);
612 start = pos;
613 }
614 we = GNUNET_malloc (sizeof (struct WatchEntry));
615 we->client = client;
616 GNUNET_SERVER_client_keep (client);
617 we->wid = ce->max_wid++;
618 GNUNET_CONTAINER_DLL_insert (pos->we_head,
619 pos->we_tail,
620 we);
621 if (pos->value != 0)
622 notify_change (pos);
623 GNUNET_SERVER_receive_done (client,
624 GNUNET_OK);
625}
626
627
628/**
423 * Task run during shutdown. 629 * Task run during shutdown.
424 * 630 *
425 * @param cls unused 631 * @param cls unused
@@ -429,7 +635,84 @@ static void
429shutdown_task (void *cls, 635shutdown_task (void *cls,
430 const struct GNUNET_SCHEDULER_TaskContext *tc) 636 const struct GNUNET_SCHEDULER_TaskContext *tc)
431{ 637{
638 struct ClientEntry *ce;
639 struct WatchEntry *we;
640 struct StatsEntry *se;
641
432 save (); 642 save ();
643 GNUNET_SERVER_notification_context_destroy (nc);
644 nc = NULL;
645 while (NULL != (ce = client_head))
646 {
647 GNUNET_SERVER_client_drop (ce->client);
648 GNUNET_CONTAINER_DLL_remove (client_head,
649 client_tail,
650 ce);
651 GNUNET_free (ce);
652 }
653 while (NULL != (se = start))
654 {
655 start = se->next;
656 while (NULL != (we = se->we_head))
657 {
658 GNUNET_SERVER_client_drop (we->client);
659 GNUNET_CONTAINER_DLL_remove (se->we_head,
660 se->we_tail,
661 we);
662 GNUNET_free (we);
663 }
664 GNUNET_free (se);
665 }
666}
667
668
669/**
670 * A client disconnected. Remove all of its data structure entries.
671 *
672 * @param cls closure, NULL
673 * @param client identification of the client
674 */
675static void
676handle_client_disconnect (void *cls,
677 struct GNUNET_SERVER_Client
678 * client)
679{
680 struct ClientEntry *ce;
681 struct WatchEntry *we;
682 struct WatchEntry *wen;
683 struct StatsEntry *se;
684
685 ce = client_head;
686 while (NULL != ce)
687 {
688 if (ce->client == client)
689 {
690 GNUNET_SERVER_client_drop (ce->client);
691 GNUNET_CONTAINER_DLL_remove (client_head,
692 client_tail,
693 ce);
694 GNUNET_free (ce);
695 break;
696 }
697 ce = ce->next;
698 }
699 se = start;
700 while (NULL != se)
701 {
702 wen = se->we_head;
703 while (NULL != (we = wen))
704 {
705 wen = we->next;
706 if (we->client != client)
707 continue;
708 GNUNET_SERVER_client_drop (we->client);
709 GNUNET_CONTAINER_DLL_remove (se->we_head,
710 se->we_tail,
711 we);
712 GNUNET_free (we);
713 }
714 se = se->next;
715 }
433} 716}
434 717
435 718
@@ -450,10 +733,15 @@ run (void *cls,
450 static const struct GNUNET_SERVER_MessageHandler handlers[] = { 733 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
451 {&handle_set, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_SET, 0}, 734 {&handle_set, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_SET, 0},
452 {&handle_get, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_GET, 0}, 735 {&handle_get, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_GET, 0},
736 {&handle_watch, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_WATCH, 0},
453 {NULL, NULL, 0, 0} 737 {NULL, NULL, 0, 0}
454 }; 738 };
455 cfg = c; 739 cfg = c;
456 GNUNET_SERVER_add_handlers (server, handlers); 740 GNUNET_SERVER_add_handlers (server, handlers);
741 nc = GNUNET_SERVER_notification_context_create (server, 16);
742 GNUNET_SERVER_disconnect_notify (server,
743 &handle_client_disconnect,
744 NULL);
457 load (server); 745 load (server);
458 GNUNET_SCHEDULER_add_delayed (sched, 746 GNUNET_SCHEDULER_add_delayed (sched,
459 GNUNET_TIME_UNIT_FOREVER_REL, 747 GNUNET_TIME_UNIT_FOREVER_REL,
diff --git a/src/statistics/statistics.h b/src/statistics/statistics.h
index c4a79765a..070a0aba5 100644
--- a/src/statistics/statistics.h
+++ b/src/statistics/statistics.h
@@ -91,4 +91,43 @@ struct GNUNET_STATISTICS_SetMessage
91 91
92}; 92};
93 93
94
95/**
96 * Message transmitted if a watched value changes.
97 */
98struct GNUNET_STATISTICS_WatchValueMessage
99{
100 /**
101 * Type: GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE
102 */
103 struct GNUNET_MessageHeader header;
104
105 /**
106 * 0 for absolute value, 1 for relative value; 2 to make persistent
107 * (see GNUNET_STATISTICS_SETFLAG_*).
108 */
109 uint32_t flags GNUNET_PACKED;
110
111 /**
112 * Unique watch identification number (watch
113 * requests are enumerated in the order they
114 * are received, the first request having
115 * a wid of zero).
116 */
117 uint32_t wid GNUNET_PACKED;
118
119 /**
120 * Reserved (always 0).
121 */
122 uint32_t reserved GNUNET_PACKED;
123
124 /**
125 * Value. Note that if this is a relative value, it will
126 * be signed even though the type given here is unsigned.
127 */
128 uint64_t value GNUNET_PACKED;
129
130};
131
132
94#endif 133#endif
diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c
index 9de9f78fd..a5dde0e55 100644
--- a/src/statistics/statistics_api.c
+++ b/src/statistics/statistics_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -25,6 +25,7 @@
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_client_lib.h" 27#include "gnunet_client_lib.h"
28#include "gnunet_constants.h"
28#include "gnunet_container_lib.h" 29#include "gnunet_container_lib.h"
29#include "gnunet_protocols.h" 30#include "gnunet_protocols.h"
30#include "gnunet_server_lib.h" 31#include "gnunet_server_lib.h"
@@ -47,7 +48,37 @@ enum ActionType
47{ 48{
48 ACTION_GET, 49 ACTION_GET,
49 ACTION_SET, 50 ACTION_SET,
50 ACTION_UPDATE 51 ACTION_UPDATE,
52 ACTION_WATCH
53};
54
55
56/**
57 * Entry kept for each value we are watching.
58 */
59struct GNUNET_STATISTICS_WatchEntry
60{
61
62 /**
63 * What subsystem is this action about? (never NULL)
64 */
65 char *subsystem;
66
67 /**
68 * What value is this action about? (never NULL)
69 */
70 char *name;
71
72 /**
73 * Function to call
74 */
75 GNUNET_STATISTICS_Iterator proc;
76
77 /**
78 * Closure for proc
79 */
80 void *proc_cls;
81
51}; 82};
52 83
53 84
@@ -118,7 +149,7 @@ struct GNUNET_STATISTICS_GetHandle
118 int aborted; 149 int aborted;
119 150
120 /** 151 /**
121 * Is this a GET, SET or UPDATE? 152 * Is this a GET, SET, UPDATE or WATCH?
122 */ 153 */
123 enum ActionType type; 154 enum ActionType type;
124 155
@@ -179,14 +210,103 @@ struct GNUNET_STATISTICS_Handle
179 struct GNUNET_STATISTICS_GetHandle *current; 210 struct GNUNET_STATISTICS_GetHandle *current;
180 211
181 /** 212 /**
213 * Array of watch entries.
214 */
215 struct GNUNET_STATISTICS_WatchEntry **watches;
216
217 /**
218 * Task doing exponential back-off trying to reconnect.
219 */
220 GNUNET_SCHEDULER_TaskIdentifier backoff_task;
221
222 /**
223 * Time for next connect retry.
224 */
225 struct GNUNET_TIME_Relative backoff;
226
227 /**
228 * Size of the 'watches' array.
229 */
230 unsigned int watches_size;
231
232 /**
182 * Should this handle auto-destruct once all actions have 233 * Should this handle auto-destruct once all actions have
183 * been processed? 234 * been processed?
184 */ 235 */
185 int do_destroy; 236 int do_destroy;
186 237
238 /**
239 * Are we currently receiving from the service?
240 */
241 int receiving;
242
187}; 243};
188 244
189 245
246
247/**
248 * Schedule the next action to be performed.
249 */
250static void schedule_action (struct GNUNET_STATISTICS_Handle *h);
251
252/**
253 * Try to (re)connect to the statistics service.
254 *
255 * @return GNUNET_YES on success, GNUNET_NO on failure.
256 */
257static int
258try_connect (struct GNUNET_STATISTICS_Handle *ret);
259
260
261static void
262insert_ai (struct GNUNET_STATISTICS_Handle *h, struct GNUNET_STATISTICS_GetHandle *ai)
263{
264 GNUNET_CONTAINER_DLL_insert_after (h->action_head,
265 h->action_tail,
266 h->action_tail,
267 ai);
268 if (h->action_head == ai)
269 schedule_action (h);
270}
271
272
273static void
274schedule_watch_request (struct GNUNET_STATISTICS_Handle *h,
275 struct GNUNET_STATISTICS_WatchEntry *watch)
276{
277
278 struct GNUNET_STATISTICS_GetHandle *ai;
279 size_t slen;
280 size_t nlen;
281 size_t nsize;
282
283 GNUNET_assert (h != NULL);
284 if (GNUNET_YES != try_connect (h))
285 {
286 schedule_action (h);
287 return;
288 }
289 slen = strlen (watch->subsystem) + 1;
290 nlen = strlen (watch->name) + 1;
291 nsize = sizeof (struct GNUNET_MessageHeader) + slen + nlen;
292 if (nsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
293 {
294 GNUNET_break (0);
295 return;
296 }
297 ai = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_GetHandle));
298 ai->sh = h;
299 ai->subsystem = GNUNET_strdup (watch->subsystem);
300 ai->name = GNUNET_strdup (watch->name);
301 ai->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
302 ai->msize = nsize;
303 ai->type = ACTION_WATCH;
304 ai->proc = watch->proc;
305 ai->cls = watch->proc_cls;
306 insert_ai (h, ai);
307}
308
309
190/** 310/**
191 * Try to (re)connect to the statistics service. 311 * Try to (re)connect to the statistics service.
192 * 312 *
@@ -195,11 +315,16 @@ struct GNUNET_STATISTICS_Handle
195static int 315static int
196try_connect (struct GNUNET_STATISTICS_Handle *ret) 316try_connect (struct GNUNET_STATISTICS_Handle *ret)
197{ 317{
318 unsigned int i;
198 if (ret->client != NULL) 319 if (ret->client != NULL)
199 return GNUNET_YES; 320 return GNUNET_YES;
200 ret->client = GNUNET_CLIENT_connect (ret->sched, "statistics", ret->cfg); 321 ret->client = GNUNET_CLIENT_connect (ret->sched, "statistics", ret->cfg);
201 if (ret->client != NULL) 322 if (ret->client != NULL)
202 return GNUNET_YES; 323 {
324 for (i=0;i<ret->watches_size;i++)
325 schedule_watch_request (ret, ret->watches[i]);
326 return GNUNET_YES;
327 }
203#if DEBUG_STATISTICS 328#if DEBUG_STATISTICS
204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
205 _("Failed to connect to statistics service!\n")); 330 _("Failed to connect to statistics service!\n"));
@@ -221,12 +346,6 @@ free_action_item (struct GNUNET_STATISTICS_GetHandle *ai)
221 346
222 347
223/** 348/**
224 * Schedule the next action to be performed.
225 */
226static void schedule_action (struct GNUNET_STATISTICS_Handle *h);
227
228
229/**
230 * GET processing is complete, tell client about it. 349 * GET processing is complete, tell client about it.
231 */ 350 */
232static void 351static void
@@ -259,7 +378,13 @@ process_message (struct GNUNET_STATISTICS_Handle *h,
259 uint16_t size; 378 uint16_t size;
260 379
261 if (h->current->aborted) 380 if (h->current->aborted)
262 return GNUNET_OK; /* don't bother */ 381 {
382#if DEBUG_STATISTICS
383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
384 "Iteration was aborted, ignoring VALUE\n");
385#endif
386 return GNUNET_OK; /* don't bother */
387 }
263 size = ntohs (msg->size); 388 size = ntohs (msg->size);
264 if (size < sizeof (struct GNUNET_STATISTICS_ReplyMessage)) 389 if (size < sizeof (struct GNUNET_STATISTICS_ReplyMessage))
265 { 390 {
@@ -293,6 +418,42 @@ process_message (struct GNUNET_STATISTICS_Handle *h,
293#endif 418#endif
294 h->current->aborted = GNUNET_YES; 419 h->current->aborted = GNUNET_YES;
295 } 420 }
421#if DEBUG_STATISTICS
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
423 "VALUE processed successfully\n");
424#endif
425 return GNUNET_OK;
426}
427
428
429static int
430process_watch_value (struct GNUNET_STATISTICS_Handle *h,
431 const struct GNUNET_MessageHeader *msg)
432{
433 const struct GNUNET_STATISTICS_WatchValueMessage *wvm;
434 struct GNUNET_STATISTICS_WatchEntry *w;
435 uint32_t wid;
436
437 if (sizeof(struct GNUNET_STATISTICS_WatchValueMessage) !=
438 ntohs (msg->size))
439 {
440 GNUNET_break (0);
441 return GNUNET_SYSERR;
442 }
443 wvm = (const struct GNUNET_STATISTICS_WatchValueMessage *)msg;
444 wid = ntohl (wvm->wid);
445 if (wid >= h->watches_size)
446 {
447 GNUNET_break (0);
448 return GNUNET_SYSERR;
449 }
450 w = h->watches[wid];
451 (void) w->proc (w->proc_cls,
452 w->subsystem,
453 w->name,
454 GNUNET_ntohll (wvm->value),
455 0 !=
456 (ntohl (wvm->flags) & GNUNET_STATISTICS_PERSIST_BIT));
296 return GNUNET_OK; 457 return GNUNET_OK;
297} 458}
298 459
@@ -329,21 +490,53 @@ receive_stats (void *cls, const struct GNUNET_MessageHeader *msg)
329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
330 "Received end of statistics marker\n"); 491 "Received end of statistics marker\n");
331#endif 492#endif
493 h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
332 finish (h, GNUNET_OK); 494 finish (h, GNUNET_OK);
495 if (h->watches_size > 0)
496 {
497 GNUNET_CLIENT_receive (h->client,
498 &receive_stats,
499 h,
500 GNUNET_TIME_UNIT_FOREVER_REL);
501 }
502 else
503 {
504 h->receiving = GNUNET_NO;
505 }
333 return; 506 return;
334 case GNUNET_MESSAGE_TYPE_STATISTICS_VALUE: 507 case GNUNET_MESSAGE_TYPE_STATISTICS_VALUE:
335 if (GNUNET_OK == process_message (h, msg)) 508 if (GNUNET_OK == process_message (h, msg))
336 { 509 {
337 /* finally, look for more! */ 510 /* finally, look for more! */
511#if DEBUG_STATISTICS
512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
513 "Processing VALUE done, now reading more\n");
514#endif
338 GNUNET_CLIENT_receive (h->client, 515 GNUNET_CLIENT_receive (h->client,
339 &receive_stats, 516 &receive_stats,
340 h, 517 h,
341 GNUNET_TIME_absolute_get_remaining 518 GNUNET_TIME_absolute_get_remaining
342 (h->current->timeout)); 519 (h->current->timeout));
520 h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
343 return; 521 return;
344 } 522 }
345 GNUNET_break (0); 523 GNUNET_break (0);
346 break; 524 break;
525 case GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE:
526 if (GNUNET_OK ==
527 process_watch_value (h,
528 msg))
529 {
530 h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
531 GNUNET_assert (h->watches_size > 0);
532 GNUNET_CLIENT_receive (h->client,
533 &receive_stats,
534 h,
535 GNUNET_TIME_UNIT_FOREVER_REL);
536 return;
537 }
538 GNUNET_break (0);
539 break;
347 default: 540 default:
348 GNUNET_break (0); 541 GNUNET_break (0);
349 break; 542 break;
@@ -392,15 +585,69 @@ transmit_get (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf)
392 2, 585 2,
393 handle->current->subsystem, 586 handle->current->subsystem,
394 handle->current->name)); 587 handle->current->name));
395 GNUNET_CLIENT_receive (handle->client, 588 if (! handle->receiving)
396 &receive_stats, 589 {
397 handle, 590#if DEBUG_STATISTICS
398 GNUNET_TIME_absolute_get_remaining (handle-> 591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
399 current->timeout)); 592 "Transmission of GET done, now reading response\n");
593#endif
594 handle->receiving = GNUNET_YES;
595 GNUNET_CLIENT_receive (handle->client,
596 &receive_stats,
597 handle,
598 GNUNET_TIME_absolute_get_remaining (handle->
599 current->timeout));
600 }
400 return msize; 601 return msize;
401} 602}
402 603
403 604
605/**
606 * Transmit a WATCH request (and if successful, start to receive
607 * the response).
608 */
609static size_t
610transmit_watch (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf)
611{
612 struct GNUNET_MessageHeader *hdr;
613 size_t slen1;
614 size_t slen2;
615 uint16_t msize;
616
617 if (buf == NULL)
618 {
619 /* timeout / error */
620#if DEBUG_STATISTICS
621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
622 "Transmission of request for statistics failed!\n");
623#endif
624 finish (handle, GNUNET_SYSERR);
625 return 0;
626 }
627 slen1 = strlen (handle->current->subsystem) + 1;
628 slen2 = strlen (handle->current->name) + 1;
629 msize = slen1 + slen2 + sizeof (struct GNUNET_MessageHeader);
630 GNUNET_assert (msize <= size);
631 hdr = (struct GNUNET_MessageHeader *) buf;
632 hdr->size = htons (msize);
633 hdr->type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH);
634 GNUNET_assert (slen1 + slen2 ==
635 GNUNET_STRINGS_buffer_fill ((char *) &hdr[1],
636 slen1 + slen2,
637 2,
638 handle->current->subsystem,
639 handle->current->name));
640 if (! handle->receiving)
641 {
642 handle->receiving = GNUNET_YES;
643 GNUNET_CLIENT_receive (handle->client,
644 &receive_stats,
645 handle,
646 GNUNET_TIME_UNIT_FOREVER_REL);
647 }
648 return msize;
649}
650
404 651
405/** 652/**
406 * Transmit a SET/UPDATE request. 653 * Transmit a SET/UPDATE request.
@@ -464,6 +711,9 @@ transmit_action (void *cls, size_t size, void *buf)
464 case ACTION_UPDATE: 711 case ACTION_UPDATE:
465 ret = transmit_set (handle, size, buf); 712 ret = transmit_set (handle, size, buf);
466 break; 713 break;
714 case ACTION_WATCH:
715 ret = transmit_watch (handle, size, buf);
716 break;
467 default: 717 default:
468 ret = 0; 718 ret = 0;
469 GNUNET_break (0); 719 GNUNET_break (0);
@@ -495,6 +745,7 @@ GNUNET_STATISTICS_create (struct GNUNET_SCHEDULER_Handle *sched,
495 ret->sched = sched; 745 ret->sched = sched;
496 ret->cfg = cfg; 746 ret->cfg = cfg;
497 ret->subsystem = GNUNET_strdup (subsystem); 747 ret->subsystem = GNUNET_strdup (subsystem);
748 ret->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
498 try_connect (ret); 749 try_connect (ret);
499 return ret; 750 return ret;
500} 751}
@@ -516,7 +767,11 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h,
516 struct GNUNET_STATISTICS_GetHandle *next; 767 struct GNUNET_STATISTICS_GetHandle *next;
517 struct GNUNET_STATISTICS_GetHandle *prev; 768 struct GNUNET_STATISTICS_GetHandle *prev;
518 struct GNUNET_TIME_Relative timeout; 769 struct GNUNET_TIME_Relative timeout;
770 int i;
519 771
772 if (GNUNET_SCHEDULER_NO_TASK != h->backoff_task)
773 GNUNET_SCHEDULER_cancel (h->sched,
774 h->backoff_task);
520 if (sync_first) 775 if (sync_first)
521 { 776 {
522 if (h->current != NULL) 777 if (h->current != NULL)
@@ -591,11 +846,30 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h,
591 GNUNET_CLIENT_disconnect (h->client, GNUNET_YES); 846 GNUNET_CLIENT_disconnect (h->client, GNUNET_YES);
592 h->client = NULL; 847 h->client = NULL;
593 } 848 }
849 for (i=0;i<h->watches_size;i++)
850 {
851 GNUNET_free (h->watches[i]->subsystem);
852 GNUNET_free (h->watches[i]->name);
853 GNUNET_free (h->watches[i]);
854 }
855 GNUNET_array_grow (h->watches,
856 h->watches_size,
857 0);
594 GNUNET_free (h->subsystem); 858 GNUNET_free (h->subsystem);
595 GNUNET_free (h); 859 GNUNET_free (h);
596} 860}
597 861
598 862
863static void
864finish_task (void *cls,
865 const struct GNUNET_SCHEDULER_TaskContext *tc)
866{
867 struct GNUNET_STATISTICS_Handle *h = cls;
868
869 h->backoff_task = GNUNET_SCHEDULER_NO_TASK;
870 finish (h, GNUNET_SYSERR);
871}
872
599 873
600/** 874/**
601 * Schedule the next action to be performed. 875 * Schedule the next action to be performed.
@@ -609,7 +883,13 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h)
609 return; /* action already pending */ 883 return; /* action already pending */
610 if (GNUNET_YES != try_connect (h)) 884 if (GNUNET_YES != try_connect (h))
611 { 885 {
612 finish (h, GNUNET_SYSERR); 886 h->backoff_task = GNUNET_SCHEDULER_add_delayed (h->sched,
887 h->backoff,
888 &finish_task,
889 h);
890 h->backoff = GNUNET_TIME_relative_multiply (h->backoff, 2);
891 h->backoff = GNUNET_TIME_relative_min (h->backoff,
892 GNUNET_CONSTANTS_SERVICE_TIMEOUT);
613 return; 893 return;
614 } 894 }
615 895
@@ -643,19 +923,6 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h)
643 } 923 }
644} 924}
645 925
646
647static void
648insert_ai (struct GNUNET_STATISTICS_Handle *h, struct GNUNET_STATISTICS_GetHandle *ai)
649{
650 GNUNET_CONTAINER_DLL_insert_after (h->action_head,
651 h->action_tail,
652 h->action_tail,
653 ai);
654 if (h->action_head == ai)
655 schedule_action (h);
656}
657
658
659/** 926/**
660 * Get statistic from the peer. 927 * Get statistic from the peer.
661 * 928 *
@@ -742,6 +1009,40 @@ GNUNET_STATISTICS_get_cancel (struct GNUNET_STATISTICS_GetHandle *gh)
742} 1009}
743 1010
744 1011
1012/**
1013 * Watch statistics from the peer (be notified whenever they change).
1014 * Note that the only way to cancel a "watch" request is to destroy
1015 * the statistics handle given as the first argument to this call.
1016 *
1017 * @param handle identification of the statistics service
1018 * @param subsystem limit to the specified subsystem, never NULL
1019 * @param name name of the statistic value, never NULL
1020 * @param proc function to call on each value
1021 * @param proc_cls closure for proc
1022 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1023 */
1024int
1025GNUNET_STATISTICS_watch (struct GNUNET_STATISTICS_Handle *handle,
1026 const char *subsystem,
1027 const char *name,
1028 GNUNET_STATISTICS_Iterator proc,
1029 void *proc_cls)
1030{
1031 struct GNUNET_STATISTICS_WatchEntry *w;
1032
1033 w = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_WatchEntry));
1034 w->subsystem = GNUNET_strdup (subsystem);
1035 w->name = GNUNET_strdup (name);
1036 w->proc = proc;
1037 w->proc_cls = proc_cls;
1038 GNUNET_array_append (handle->watches,
1039 handle->watches_size,
1040 w);
1041 schedule_watch_request (handle, w);
1042 return GNUNET_OK;
1043}
1044
1045
745static void 1046static void
746add_setter_action (struct GNUNET_STATISTICS_Handle *h, 1047add_setter_action (struct GNUNET_STATISTICS_Handle *h,
747 const char *name, 1048 const char *name,
@@ -809,7 +1110,8 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h,
809 ai->type = type; 1110 ai->type = type;
810 } 1111 }
811 } 1112 }
812 ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); 1113 ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT);
1114 ai->make_persistent = make_persistent;
813 return; 1115 return;
814 } 1116 }
815 ai = ai->next; 1117 ai = ai->next;
@@ -824,7 +1126,6 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h,
824 ai->value = value; 1126 ai->value = value;
825 ai->type = type; 1127 ai->type = type;
826 insert_ai (h, ai); 1128 insert_ai (h, ai);
827 schedule_action (h);
828} 1129}
829 1130
830 1131
diff --git a/src/statistics/test_statistics_api.c b/src/statistics/test_statistics_api.c
index 378e17d0c..5c55a11a6 100644
--- a/src/statistics/test_statistics_api.c
+++ b/src/statistics/test_statistics_api.c
@@ -29,7 +29,7 @@
29#include "gnunet_scheduler_lib.h" 29#include "gnunet_scheduler_lib.h"
30#include "gnunet_statistics_service.h" 30#include "gnunet_statistics_service.h"
31 31
32#define VERBOSE GNUNET_NO 32#define DEBUG_STATISTICS GNUNET_NO
33 33
34#define START_SERVICE GNUNET_YES 34#define START_SERVICE GNUNET_YES
35 35
@@ -38,6 +38,11 @@ check_1 (void *cls,
38 const char *subsystem, 38 const char *subsystem,
39 const char *name, uint64_t value, int is_persistent) 39 const char *name, uint64_t value, int is_persistent)
40{ 40{
41 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
42 "Received value %llu for `%s:%s\n",
43 (unsigned long long) value,
44 subsystem,
45 name);
41 GNUNET_assert (0 == strcmp (name, "test-1")); 46 GNUNET_assert (0 == strcmp (name, "test-1"));
42 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api")); 47 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api"));
43 GNUNET_assert (value == 1); 48 GNUNET_assert (value == 1);
@@ -50,6 +55,11 @@ check_2 (void *cls,
50 const char *subsystem, 55 const char *subsystem,
51 const char *name, uint64_t value, int is_persistent) 56 const char *name, uint64_t value, int is_persistent)
52{ 57{
58 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
59 "Received value %llu for `%s:%s\n",
60 (unsigned long long) value,
61 subsystem,
62 name);
53 GNUNET_assert (0 == strcmp (name, "test-2")); 63 GNUNET_assert (0 == strcmp (name, "test-2"));
54 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api")); 64 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api"));
55 GNUNET_assert (value == 2); 65 GNUNET_assert (value == 2);
@@ -62,6 +72,11 @@ check_3 (void *cls,
62 const char *subsystem, 72 const char *subsystem,
63 const char *name, uint64_t value, int is_persistent) 73 const char *name, uint64_t value, int is_persistent)
64{ 74{
75 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
76 "Received value %llu for `%s:%s\n",
77 (unsigned long long) value,
78 subsystem,
79 name);
65 GNUNET_assert (0 == strcmp (name, "test-3")); 80 GNUNET_assert (0 == strcmp (name, "test-3"));
66 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api")); 81 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api"));
67 GNUNET_assert (value == 3); 82 GNUNET_assert (value == 3);
@@ -85,6 +100,8 @@ static void
85next (void *cls, int success) 100next (void *cls, int success)
86{ 101{
87 GNUNET_assert (success == GNUNET_OK); 102 GNUNET_assert (success == GNUNET_OK);
103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
104 "Issuing GET request\n");
88 GNUNET_break (NULL != 105 GNUNET_break (NULL !=
89 GNUNET_STATISTICS_get (h, NULL, "test-2", 106 GNUNET_STATISTICS_get (h, NULL, "test-2",
90 GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, cls)); 107 GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, cls));
@@ -102,6 +119,8 @@ run (void *cls,
102 GNUNET_STATISTICS_set (h, "test-2", 2, GNUNET_NO); 119 GNUNET_STATISTICS_set (h, "test-2", 2, GNUNET_NO);
103 GNUNET_STATISTICS_set (h, "test-3", 2, GNUNET_NO); 120 GNUNET_STATISTICS_set (h, "test-3", 2, GNUNET_NO);
104 GNUNET_STATISTICS_update (h, "test-3", 1, GNUNET_YES); 121 GNUNET_STATISTICS_update (h, "test-3", 1, GNUNET_YES);
122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
123 "Issuing GET request\n");
105 GNUNET_break (NULL != 124 GNUNET_break (NULL !=
106 GNUNET_STATISTICS_get (h, NULL, "test-1", 125 GNUNET_STATISTICS_get (h, NULL, "test-1",
107 GNUNET_TIME_UNIT_SECONDS, &next, &check_1, cls)); 126 GNUNET_TIME_UNIT_SECONDS, &next, &check_1, cls));
@@ -127,6 +146,11 @@ check ()
127 char *const argv[] = { "test-statistics-api", 146 char *const argv[] = { "test-statistics-api",
128 "-c", 147 "-c",
129 "test_statistics_api_data.conf", 148 "test_statistics_api_data.conf",
149#if DEBUG_STATISTICS
150 "-L", "DEBUG",
151#else
152 "-L", "WARNING",
153#endif
130 NULL 154 NULL
131 }; 155 };
132 struct GNUNET_GETOPT_CommandLineOption options[] = { 156 struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -141,7 +165,7 @@ check ()
141#endif 165#endif
142 "-c", "test_statistics_api_data.conf", NULL); 166 "-c", "test_statistics_api_data.conf", NULL);
143#endif 167#endif
144 GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp", 168 GNUNET_PROGRAM_run (5, argv, "test-statistics-api", "nohelp",
145 options, &run, &ok); 169 options, &run, &ok);
146#if START_SERVICE 170#if START_SERVICE
147 if (0 != PLIBC_KILL (pid, SIGTERM)) 171 if (0 != PLIBC_KILL (pid, SIGTERM))
@@ -163,7 +187,7 @@ check ()
163#endif 187#endif
164 "-c", "test_statistics_api_data.conf", NULL); 188 "-c", "test_statistics_api_data.conf", NULL);
165#endif 189#endif
166 GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp", 190 GNUNET_PROGRAM_run (5, argv, "test-statistics-api", "nohelp",
167 options, &run_more, &ok); 191 options, &run_more, &ok);
168#if START_SERVICE 192#if START_SERVICE
169 if (0 != PLIBC_KILL (pid, SIGTERM)) 193 if (0 != PLIBC_KILL (pid, SIGTERM))
@@ -181,6 +205,13 @@ main (int argc, char *argv[])
181{ 205{
182 int ret; 206 int ret;
183 207
208 GNUNET_log_setup ("test_statistics_api",
209#if DEBUG_STATISTICS
210 "DEBUG",
211#else
212 "WARNING",
213#endif
214 NULL);
184 ret = check (); 215 ret = check ();
185 216
186 return ret; 217 return ret;
diff --git a/src/statistics/test_statistics_api_data.conf b/src/statistics/test_statistics_api_data.conf
index 41cfd9596..ba8d4d68e 100644
--- a/src/statistics/test_statistics_api_data.conf
+++ b/src/statistics/test_statistics_api_data.conf
@@ -4,9 +4,12 @@ DEFAULTCONFIG = test_statistics_api_data.conf
4 4
5[statistics] 5[statistics]
6PORT = 22353 6PORT = 22353
7UNIXPATH = /tmp/test-statistics-service-statistics.unix
8DEBUG = YES
7 9
8[arm] 10[arm]
9PORT = 22354 11PORT = 22354
10DEFAULTSERVICES = 12DEFAULTSERVICES =
13UNIXPATH = /tmp/test-statistics-service-arm.unix
11# DEBUG = YES 14# DEBUG = YES
12 15
diff --git a/src/testing/test_testing_topology.c b/src/testing/test_testing_topology.c
index 6450d67d3..4701d2c84 100644
--- a/src/testing/test_testing_topology.c
+++ b/src/testing/test_testing_topology.c
@@ -443,14 +443,14 @@ init_notify_peer1 (void *cls,
443 * Connect to the receiving peer 443 * Connect to the receiving peer
444 */ 444 */
445 pos->peer2handle = GNUNET_CORE_connect (sched, 445 pos->peer2handle = GNUNET_CORE_connect (sched,
446 pos->peer2->cfg, 446 pos->peer2->cfg,
447 TIMEOUT, 447 TIMEOUT,
448 pos, 448 pos,
449 &init_notify_peer2, 449 &init_notify_peer2,
450 NULL, 450 NULL,
451 NULL, 451 NULL,
452 NULL, 452 NULL, NULL,
453 GNUNET_YES, NULL, GNUNET_YES, handlers); 453 GNUNET_YES, NULL, GNUNET_YES, handlers);
454 454
455} 455}
456 456
@@ -485,7 +485,7 @@ send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
485 TIMEOUT, 485 TIMEOUT,
486 pos, 486 pos,
487 &init_notify_peer1, 487 &init_notify_peer1,
488 NULL, 488 NULL, NULL,
489 NULL, 489 NULL,
490 NULL, 490 NULL,
491 GNUNET_NO, NULL, GNUNET_NO, no_handlers); 491 GNUNET_NO, NULL, GNUNET_NO, no_handlers);
diff --git a/src/testing/testing.c b/src/testing/testing.c
index 3ccb445e4..d12892fcc 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -513,7 +513,7 @@ start_fsm (void *cls,
513 ARM_START_WAIT, 513 ARM_START_WAIT,
514 d, 514 d,
515 &testing_init, 515 &testing_init,
516 NULL, NULL, 516 NULL, NULL, NULL,
517 NULL, GNUNET_NO, 517 NULL, GNUNET_NO,
518 NULL, GNUNET_NO, no_handlers); 518 NULL, GNUNET_NO, no_handlers);
519 break; 519 break;
@@ -1380,7 +1380,7 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
1380 timeout, 1380 timeout,
1381 ctx, 1381 ctx,
1382 NULL, 1382 NULL,
1383 &connect_notify, NULL, 1383 &connect_notify, NULL, NULL,
1384 NULL, GNUNET_NO, 1384 NULL, GNUNET_NO,
1385 NULL, GNUNET_NO, no_handlers); 1385 NULL, GNUNET_NO, no_handlers);
1386 if (ctx->d1core == NULL) 1386 if (ctx->d1core == NULL)
@@ -1442,7 +1442,7 @@ reattempt_daemons_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext
1442 GNUNET_TIME_absolute_get_remaining(ctx->timeout), 1442 GNUNET_TIME_absolute_get_remaining(ctx->timeout),
1443 ctx, 1443 ctx,
1444 NULL, 1444 NULL,
1445 &connect_notify, NULL, 1445 &connect_notify, NULL, NULL,
1446 NULL, GNUNET_NO, 1446 NULL, GNUNET_NO,
1447 NULL, GNUNET_NO, no_handlers); 1447 NULL, GNUNET_NO, no_handlers);
1448 if (ctx->d1core == NULL) 1448 if (ctx->d1core == NULL)
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c
index e2ae4a107..d39c89d36 100644
--- a/src/topology/gnunet-daemon-topology.c
+++ b/src/topology/gnunet-daemon-topology.c
@@ -934,13 +934,11 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
934 * @param cls closure (not used) 934 * @param cls closure (not used)
935 * @param peer potential peer to connect to 935 * @param peer potential peer to connect to
936 * @param hello HELLO for this peer (or NULL) 936 * @param hello HELLO for this peer (or NULL)
937 * @param trust how much we trust the peer (not used)
938 */ 937 */
939static void 938static void
940process_peer (void *cls, 939process_peer (void *cls,
941 const struct GNUNET_PeerIdentity *peer, 940 const struct GNUNET_PeerIdentity *peer,
942 const struct GNUNET_HELLO_Message *hello, 941 const struct GNUNET_HELLO_Message *hello)
943 uint32_t trust)
944{ 942{
945 struct Peer *pos; 943 struct Peer *pos;
946 944
@@ -1404,7 +1402,8 @@ run (void *cls,
1404 NULL, 1402 NULL,
1405 &core_init, 1403 &core_init,
1406 &connect_notify, 1404 &connect_notify,
1407 &disconnect_notify, 1405 &disconnect_notify,
1406 NULL,
1408 NULL, GNUNET_NO, 1407 NULL, GNUNET_NO,
1409 NULL, GNUNET_NO, 1408 NULL, GNUNET_NO,
1410 handlers); 1409 handlers);
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index 93f064fd0..12db541ac 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -2612,13 +2612,11 @@ add_to_foreign_address_list (void *cls,
2612 * @param cls closure ('struct NeighbourList*') 2612 * @param cls closure ('struct NeighbourList*')
2613 * @param peer id of the peer, NULL for last call 2613 * @param peer id of the peer, NULL for last call
2614 * @param h hello message for the peer (can be NULL) 2614 * @param h hello message for the peer (can be NULL)
2615 * @param trust amount of trust we have in the peer (not used)
2616 */ 2615 */
2617static void 2616static void
2618add_hello_for_peer (void *cls, 2617add_hello_for_peer (void *cls,
2619 const struct GNUNET_PeerIdentity *peer, 2618 const struct GNUNET_PeerIdentity *peer,
2620 const struct GNUNET_HELLO_Message *h, 2619 const struct GNUNET_HELLO_Message *h)
2621 uint32_t trust)
2622{ 2620{
2623 struct NeighbourList *n = cls; 2621 struct NeighbourList *n = cls;
2624 2622
@@ -2706,7 +2704,7 @@ setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
2706 if (do_hello) 2704 if (do_hello)
2707 { 2705 {
2708 n->piter = GNUNET_PEERINFO_iterate (peerinfo, peer, 2706 n->piter = GNUNET_PEERINFO_iterate (peerinfo, peer,
2709 0, GNUNET_TIME_UNIT_FOREVER_REL, 2707 GNUNET_TIME_UNIT_FOREVER_REL,
2710 &add_hello_for_peer, n); 2708 &add_hello_for_peer, n);
2711 transmit_to_peer (NULL, NULL, 0, 2709 transmit_to_peer (NULL, NULL, 0,
2712 HELLO_ADDRESS_EXPIRATION, 2710 HELLO_ADDRESS_EXPIRATION,
@@ -3870,13 +3868,11 @@ run_validation (void *cls,
3870 * @param cls closure 3868 * @param cls closure
3871 * @param peer id of the peer, NULL for last call 3869 * @param peer id of the peer, NULL for last call
3872 * @param h hello message for the peer (can be NULL) 3870 * @param h hello message for the peer (can be NULL)
3873 * @param trust amount of trust we have in the peer (not used)
3874 */ 3871 */
3875static void 3872static void
3876check_hello_validated (void *cls, 3873check_hello_validated (void *cls,
3877 const struct GNUNET_PeerIdentity *peer, 3874 const struct GNUNET_PeerIdentity *peer,
3878 const struct GNUNET_HELLO_Message *h, 3875 const struct GNUNET_HELLO_Message *h)
3879 uint32_t trust)
3880{ 3876{
3881 struct CheckHelloValidatedContext *chvc = cls; 3877 struct CheckHelloValidatedContext *chvc = cls;
3882 struct GNUNET_HELLO_Message *plain_hello; 3878 struct GNUNET_HELLO_Message *plain_hello;
@@ -4088,7 +4084,6 @@ process_hello (struct TransportPlugin *plugin,
4088 (continuation will then schedule actual validation) */ 4084 (continuation will then schedule actual validation) */
4089 chvc->piter = GNUNET_PEERINFO_iterate (peerinfo, 4085 chvc->piter = GNUNET_PEERINFO_iterate (peerinfo,
4090 &target, 4086 &target,
4091 0,
4092 HELLO_VERIFICATION_TIMEOUT, 4087 HELLO_VERIFICATION_TIMEOUT,
4093 &check_hello_validated, chvc); 4088 &check_hello_validated, chvc);
4094 return GNUNET_OK; 4089 return GNUNET_OK;
diff --git a/src/util/server_nc.c b/src/util/server_nc.c
index 1cf3df8bd..3bab691e9 100644
--- a/src/util/server_nc.c
+++ b/src/util/server_nc.c
@@ -164,6 +164,11 @@ handle_client_disconnect (void *cls,
164 } 164 }
165 if (pos == NULL) 165 if (pos == NULL)
166 return; 166 return;
167#if DEBUG_SERVER_NC
168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
169 "Client disconnected, cleaning up %u messages in NC queue\n",
170 pos->num_pending);
171#endif
167 if (prev == NULL) 172 if (prev == NULL)
168 nc->clients = pos->next; 173 nc->clients = pos->next;
169 else 174 else
@@ -285,6 +290,10 @@ transmit_message (void *cls,
285 if (buf == NULL) 290 if (buf == NULL)
286 { 291 {
287 /* 'cl' should be freed via disconnect notification shortly */ 292 /* 'cl' should be freed via disconnect notification shortly */
293#if DEBUG_SERVER_NC
294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
295 "Failed to transmit message from NC queue to client\n");
296#endif
288 return 0; 297 return 0;
289 } 298 }
290 ret = 0; 299 ret = 0;
@@ -310,11 +319,18 @@ transmit_message (void *cls,
310 cl->num_pending--; 319 cl->num_pending--;
311 } 320 }
312 if (cl->pending_head != NULL) 321 if (cl->pending_head != NULL)
313 cl->th = GNUNET_SERVER_notify_transmit_ready (cl->client, 322 {
314 ntohs (cl->pending_head->msg->size), 323#if DEBUG_SERVER_NC
315 GNUNET_TIME_UNIT_FOREVER_REL, 324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 &transmit_message, 325 "Have %u messages left in NC queue, will try transmission again\n",
317 cl); 326 cl->num_pending);
327#endif
328 cl->th = GNUNET_SERVER_notify_transmit_ready (cl->client,
329 ntohs (cl->pending_head->msg->size),
330 GNUNET_TIME_UNIT_FOREVER_REL,
331 &transmit_message,
332 cl);
333 }
318 return ret; 334 return ret;
319} 335}
320 336