aboutsummaryrefslogtreecommitdiff
path: root/src/peerinfo
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-05-29 00:46:26 +0000
committerChristian Grothoff <christian@grothoff.org>2009-05-29 00:46:26 +0000
commit0a217a8df1657b4334b55b0e4a6c7837a8dbcfd9 (patch)
tree6b552f40eb089db96409a312a98d9b12bd669102 /src/peerinfo
downloadgnunet-0a217a8df1657b4334b55b0e4a6c7837a8dbcfd9.tar.gz
gnunet-0a217a8df1657b4334b55b0e4a6c7837a8dbcfd9.zip
ng
Diffstat (limited to 'src/peerinfo')
-rw-r--r--src/peerinfo/Makefile.am56
-rw-r--r--src/peerinfo/gnunet-peerinfo.c152
-rw-r--r--src/peerinfo/gnunet-service-peerinfo.c708
-rw-r--r--src/peerinfo/peerinfo.h135
-rw-r--r--src/peerinfo/peerinfo_api.c302
-rw-r--r--src/peerinfo/test_peerinfo_api.c175
-rw-r--r--src/peerinfo/test_peerinfo_api_data.conf5
7 files changed, 1533 insertions, 0 deletions
diff --git a/src/peerinfo/Makefile.am b/src/peerinfo/Makefile.am
new file mode 100644
index 000000000..294ff5cca
--- /dev/null
+++ b/src/peerinfo/Makefile.am
@@ -0,0 +1,56 @@
1INCLUDES = -I$(top_srcdir)/src/include
2
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -luuid -liconv -lstdc++ -lcomdlg32 -lgdi32
5endif
6
7if USE_COVERAGE
8 AM_CFLAGS = -fprofile-arcs -ftest-coverage
9endif
10
11lib_LTLIBRARIES = libgnunetpeerinfo.la
12
13libgnunetpeerinfo_la_SOURCES = \
14 peerinfo_api.c peerinfo.h
15libgnunetpeerinfo_la_LIBADD = \
16 $(top_builddir)/src/hello/libgnunethello.la \
17 $(top_builddir)/src/util/libgnunetutil.la
18libgnunetpeerinfo_la_LDFLAGS = \
19 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
20 -version-info 0:0:0
21
22
23bin_PROGRAMS = \
24 gnunet-peerinfo \
25 gnunet-service-peerinfo
26
27gnunet_peerinfo_SOURCES = \
28 gnunet-peerinfo.c
29gnunet_peerinfo_LDADD = \
30 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
31 $(top_builddir)/src/util/libgnunetutil.la
32
33gnunet_service_peerinfo_SOURCES = \
34 gnunet-service-peerinfo.c
35gnunet_service_peerinfo_LDADD = \
36 $(top_builddir)/src/hello/libgnunethello.la \
37 $(top_builddir)/src/util/libgnunetutil.la
38
39
40check_PROGRAMS = \
41 test_peerinfo_api
42
43TESTS = $(check_PROGRAMS) # $(check_SCRIPTS)
44
45test_peerinfo_api_SOURCES = \
46 test_peerinfo_api.c
47test_peerinfo_api_LDADD = \
48 $(top_builddir)/src/hello/libgnunethello.la \
49 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
50 $(top_builddir)/src/util/libgnunetutil.la
51
52EXTRA_DIST = \
53 test_peerinfo_api_data.conf
54
55#check_SCRIPTS = \
56# test_gnunet_peerinfo.sh
diff --git a/src/peerinfo/gnunet-peerinfo.c b/src/peerinfo/gnunet-peerinfo.c
new file mode 100644
index 000000000..6c737c88a
--- /dev/null
+++ b/src/peerinfo/gnunet-peerinfo.c
@@ -0,0 +1,152 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file peerinfo/gnunet-peerinfo.c
23 * @brief Print information about other known peers.
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_crypto_lib.h"
28#include "gnunet_configuration_lib.h"
29#include "gnunet_getopt_lib.h"
30#include "gnunet_peerinfo_service.h"
31#include "gnunet_program_lib.h"
32
33static int no_resolve;
34
35static int be_quiet;
36
37static int get_self;
38
39/**
40 * Print information about the peer.
41 * Currently prints the GNUNET_PeerIdentity, trust and the IP.
42 * Could of course do more (e.g. resolve via DNS).
43 */
44static void
45print_peer_info (void *cls,
46 const struct GNUNET_PeerIdentity *peer,
47 const struct GNUNET_HELLO_Message *hello, uint32_t trust)
48{
49 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
50
51 /* FIXME: add printing of address information!
52 => need extended transport API! */
53 GNUNET_CRYPTO_hash_to_enc (&peer->hashPubKey, &enc);
54 if (be_quiet)
55 printf ("%s\n", (const char *) &enc);
56 else
57 printf (_("Peer `%s' with trust %8u\n"), (const char *) &enc, trust);
58}
59
60/**
61 * Main function that will be run by the scheduler.
62 *
63 * @param cls closure
64 * @param sched the scheduler to use
65 * @param args remaining command-line arguments
66 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
67 * @param cfg configuration
68 */
69static void
70run (void *cls,
71 struct GNUNET_SCHEDULER_Handle *sched,
72 char *const *args,
73 const char *cfgfile, struct GNUNET_CONFIGURATION_Handle *cfg)
74{
75 struct GNUNET_CRYPTO_RsaPrivateKey *priv;
76 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
77 struct GNUNET_PeerIdentity pid;
78 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
79 char *fn;
80
81 if (get_self != GNUNET_YES)
82 {
83 GNUNET_PEERINFO_for_all (cfg,
84 sched,
85 NULL,
86 0,
87 GNUNET_TIME_relative_multiply
88 (GNUNET_TIME_UNIT_SECONDS, 30),
89 &print_peer_info, NULL);
90 }
91 else
92 {
93 if (GNUNET_OK !=
94 GNUNET_CONFIGURATION_get_value_filename (cfg,
95 "GNUNET",
96 "HOSTKEYFILE", &fn))
97 return;
98 priv = GNUNET_CRYPTO_rsa_key_create_from_file (fn);
99 if (priv == NULL)
100 {
101 fprintf (stderr, _("Loading hostkey from `%s' failed.\n"), fn);
102 GNUNET_free (fn);
103 return;
104 }
105 GNUNET_free (fn);
106 GNUNET_CRYPTO_rsa_key_get_public (priv, &pub);
107 GNUNET_CRYPTO_rsa_key_free (priv);
108 GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
109 GNUNET_CRYPTO_hash_to_enc (&pid.hashPubKey, &enc);
110 if (be_quiet)
111 printf ("%s\n", (char *) &enc);
112 else
113 printf (_("I am peer `%s'.\n"), (const char *) &enc);
114 }
115}
116
117
118/**
119 * gnunet-peerinfo command line options
120 */
121static struct GNUNET_GETOPT_CommandLineOption options[] = {
122 {'n', "numeric", NULL,
123 gettext_noop ("don't resolve host names"),
124 0, &GNUNET_GETOPT_set_one, &no_resolve},
125 {'q', "quiet", NULL,
126 gettext_noop ("output only the identity strings"),
127 0, &GNUNET_GETOPT_set_one, &be_quiet},
128 {'s', "self", NULL,
129 gettext_noop ("output our own identity only"),
130 0, &GNUNET_GETOPT_set_one, &get_self},
131 GNUNET_GETOPT_OPTION_END
132};
133
134/**
135 * The main function to obtain peer information.
136 *
137 * @param argc number of arguments from the command line
138 * @param argv command line arguments
139 * @return 0 ok, 1 on error
140 */
141int
142main (int argc, char *const *argv)
143{
144 return (GNUNET_OK ==
145 GNUNET_PROGRAM_run (argc,
146 argv,
147 "gnunet-peerinfo",
148 gettext_noop ("Print information about peers."),
149 options, &run, NULL)) ? 0 : 1;
150}
151
152/* end of gnunet-peerinfo.c */
diff --git a/src/peerinfo/gnunet-service-peerinfo.c b/src/peerinfo/gnunet-service-peerinfo.c
new file mode 100644
index 000000000..b81c7b6ee
--- /dev/null
+++ b/src/peerinfo/gnunet-service-peerinfo.c
@@ -0,0 +1,708 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2004, 2005, 2007, 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file peerinfo/gnunet-service-peerinfo.c
23 * @brief maintains list of known peers
24 *
25 * Code to maintain the list of currently known hosts (in memory
26 * structure of data/hosts/ and data/credit/).
27 *
28 * @author Christian Grothoff
29 */
30
31#include "platform.h"
32#include "gnunet_crypto_lib.h"
33#include "gnunet_disk_lib.h"
34#include "gnunet_hello_lib.h"
35#include "gnunet_protocols.h"
36#include "gnunet_service_lib.h"
37#include "peerinfo.h"
38
39/**
40 * How often do we scan the HOST_DIR for new entries?
41 */
42#define DATA_HOST_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
43
44/**
45 * How often do we flush trust values to disk?
46 */
47#define TRUST_FLUSH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
48
49/**
50 * How often do we discard old entries in data/hosts/?
51 */
52#define DATA_HOST_CLEAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60)
53
54/**
55 * In-memory cache of known hosts.
56 */
57struct HostEntry
58{
59
60 /**
61 * This is a linked list.
62 */
63 struct HostEntry *next;
64
65 /**
66 * Identity of the peer.
67 */
68 struct GNUNET_PeerIdentity identity;
69
70 /**
71 * Hello for the peer (can be NULL)
72 */
73 struct GNUNET_HELLO_Message *hello;
74
75 /**
76 * Trust rating for this peer
77 */
78 uint32_t trust;
79
80 /**
81 * Trust rating for this peer on disk.
82 */
83 uint32_t disk_trust;
84
85};
86
87/**
88 * The in-memory list of known hosts.
89 */
90static struct HostEntry *hosts;
91
92/**
93 * Directory where the hellos are stored in (data/hosts)
94 */
95static char *networkIdDirectory;
96
97/**
98 * Where do we store trust information?
99 */
100static char *trustDirectory;
101
102
103/**
104 * Address iterator that causes expired entries to be discarded.
105 *
106 * @param cls pointer to the current time
107 * @return GNUNET_NO if expiration smaller than the current time
108 */
109static int
110discard_expired (void *cls,
111 const char *tname,
112 struct GNUNET_TIME_Absolute expiration,
113 const void *addr, size_t addrlen)
114{
115 const struct GNUNET_TIME_Absolute *now = cls;
116 if (now->value > expiration.value)
117 return GNUNET_NO;
118 return GNUNET_OK;
119}
120
121
122/**
123 * Get the filename under which we would store the GNUNET_HELLO_Message
124 * for the given host and protocol.
125 * @return filename of the form DIRECTORY/HOSTID
126 */
127static char *
128get_host_filename (const struct GNUNET_PeerIdentity *id)
129{
130 struct GNUNET_CRYPTO_HashAsciiEncoded fil;
131 char *fn;
132
133 GNUNET_CRYPTO_hash_to_enc (&id->hashPubKey, &fil);
134 GNUNET_asprintf (&fn,
135 "%s%s%s", networkIdDirectory, DIR_SEPARATOR_STR, &fil);
136 return fn;
137}
138
139
140/**
141 * Get the filename under which we would store the GNUNET_HELLO_Message
142 * for the given host and protocol.
143 * @return filename of the form DIRECTORY/HOSTID
144 */
145static char *
146get_trust_filename (const struct GNUNET_PeerIdentity *id)
147{
148 struct GNUNET_CRYPTO_HashAsciiEncoded fil;
149 char *fn;
150
151 GNUNET_CRYPTO_hash_to_enc (&id->hashPubKey, &fil);
152 GNUNET_asprintf (&fn, "%s%s%s", trustDirectory, DIR_SEPARATOR_STR, &fil);
153 return fn;
154}
155
156/**
157 * Find the host entry for the given peer. Call
158 * only when synchronized!
159 * @return NULL if not found
160 */
161static struct HostEntry *
162lookup_host_entry (const struct GNUNET_PeerIdentity *id)
163{
164 struct HostEntry *pos;
165
166 pos = hosts;
167 while ((pos != NULL) &&
168 (0 !=
169 memcmp (id, &pos->identity, sizeof (struct GNUNET_PeerIdentity))))
170 pos = pos->next;
171 return pos;
172}
173
174
175/**
176 * Add a host to the list.
177 *
178 * @param identity the identity of the host
179 * @param protocol the protocol for the host
180 */
181static void
182add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
183{
184 struct HostEntry *entry;
185 char *fn;
186 uint32_t trust;
187 char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
188 const struct GNUNET_HELLO_Message *hello;
189 struct GNUNET_HELLO_Message *hello_clean;
190 int size;
191 struct GNUNET_TIME_Absolute now;
192
193 entry = lookup_host_entry (identity);
194 if (entry != NULL)
195 return;
196 entry = GNUNET_malloc (sizeof (struct HostEntry));
197 entry->identity = *identity;
198 fn = get_trust_filename (identity);
199 if ((GNUNET_DISK_file_test (fn) == GNUNET_YES) &&
200 (sizeof (trust) == GNUNET_DISK_file_read (fn, sizeof (trust), &trust)))
201 entry->disk_trust = entry->trust = ntohl (trust);
202 GNUNET_free (fn);
203
204 fn = get_host_filename (identity);
205 if (GNUNET_DISK_file_test (fn) == GNUNET_YES)
206 {
207 size = GNUNET_DISK_file_read (fn, sizeof (buffer), buffer);
208 hello = (const struct GNUNET_HELLO_Message *) buffer;
209 now = GNUNET_TIME_absolute_get ();
210 hello_clean = GNUNET_HELLO_iterate_addresses (hello,
211 GNUNET_YES,
212 &discard_expired, &now);
213 entry->hello = hello_clean;
214 }
215 GNUNET_free (fn);
216 entry->next = hosts;
217 hosts = entry;
218}
219
220
221/**
222 * Increase the host credit by a value.
223 *
224 * @param hostId is the identity of the host
225 * @param value is the int value by which the
226 * host credit is to be increased or decreased
227 * @returns the actual change in trust (positive or negative)
228 */
229static int
230change_host_trust (const struct GNUNET_PeerIdentity *hostId, int value)
231{
232 struct HostEntry *host;
233
234 if (value == 0)
235 return 0;
236 host = lookup_host_entry (hostId);
237 if (host == NULL)
238 {
239 add_host_to_known_hosts (hostId);
240 host = lookup_host_entry (hostId);
241 }
242 GNUNET_assert (host != NULL);
243 if (value > 0)
244 {
245 if (host->trust + value < host->trust)
246 {
247 value = ((uint32_t) - 1) - host->trust;
248 host->trust = (uint32_t) - 1; /* maximized */
249 }
250 else
251 host->trust += value;
252 }
253 else
254 {
255 if (host->trust < -value)
256 {
257 value = -host->trust;
258 host->trust = 0;
259 }
260 else
261 host->trust += value;
262 }
263 return value;
264}
265
266
267/**
268 * Remove a file that should not be there. LOG
269 * success or failure.
270 */
271static void
272remove_garbage (const char *fullname)
273{
274 if (0 == UNLINK (fullname))
275 GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
276 _
277 ("File `%s' in directory `%s' does not match naming convention. "
278 "Removed.\n"), fullname, networkIdDirectory);
279 else
280 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR |
281 GNUNET_ERROR_TYPE_BULK, "unlink", fullname);
282}
283
284
285static int
286hosts_directory_scan_callback (void *cls, const char *fullname)
287{
288 unsigned int *matched = cls;
289 struct GNUNET_PeerIdentity identity;
290 const char *filename;
291
292 if (GNUNET_DISK_file_test (fullname) != GNUNET_YES)
293 return GNUNET_OK; /* ignore non-files */
294 if (strlen (fullname) < sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded))
295 {
296 remove_garbage (fullname);
297 return GNUNET_OK;
298 }
299 filename =
300 &fullname[strlen (fullname) -
301 sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1];
302 if (filename[-1] != DIR_SEPARATOR)
303 {
304 remove_garbage (fullname);
305 return GNUNET_OK;
306 }
307 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (filename,
308 &identity.hashPubKey))
309 {
310 remove_garbage (fullname);
311 return GNUNET_OK;
312 }
313 (*matched)++;
314 add_host_to_known_hosts (&identity);
315 return GNUNET_OK;
316}
317
318
319/**
320 * Call this method periodically to scan data/hosts for new hosts.
321 */
322static void
323cron_scan_directory_data_hosts (void *cls,
324 const struct GNUNET_SCHEDULER_TaskContext *tc)
325{
326 static unsigned int retries;
327 unsigned int count;
328
329 count = 0;
330 GNUNET_DISK_directory_scan (networkIdDirectory,
331 &hosts_directory_scan_callback, &count);
332 if ((0 == count) && (0 == (++retries & 31)))
333 GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
334 GNUNET_ERROR_TYPE_BULK,
335 _("Still no peers found in `%s'!\n"), networkIdDirectory);
336 GNUNET_SCHEDULER_add_delayed (tc->sched,
337 GNUNET_NO,
338 GNUNET_SCHEDULER_PRIORITY_KEEP,
339 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
340 DATA_HOST_FREQ,
341 &cron_scan_directory_data_hosts, NULL);
342}
343
344
345/**
346 * Bind a host address (hello) to a hostId.
347 *
348 * @param peer the peer for which this is a hello
349 * @param hello the verified (!) hello message
350 */
351static void
352bind_address (const struct GNUNET_PeerIdentity *peer,
353 const struct GNUNET_HELLO_Message *hello)
354{
355 char *fn;
356 struct HostEntry *host;
357 struct GNUNET_HELLO_Message *mrg;
358
359 add_host_to_known_hosts (peer);
360 host = lookup_host_entry (peer);
361 GNUNET_assert (host != NULL);
362 if (host->hello == NULL)
363 {
364 host->hello = GNUNET_malloc (GNUNET_HELLO_size (hello));
365 memcpy (host->hello, hello, GNUNET_HELLO_size (hello));
366 }
367 else
368 {
369 mrg = GNUNET_HELLO_merge (host->hello, hello);
370 GNUNET_free (host->hello);
371 host->hello = mrg;
372 }
373 fn = get_host_filename (peer);
374 GNUNET_DISK_file_write (fn, host->hello, GNUNET_HELLO_size (hello), "644");
375 GNUNET_free (fn);
376}
377
378
379/**
380 * Do transmit info either for only the host matching the given
381 * argument or for all known hosts and change their trust values by
382 * the given delta.
383 *
384 * @param only NULL to hit all hosts
385 */
386static void
387send_to_each_host (const struct GNUNET_PeerIdentity *only,
388 int trust_change,
389 struct GNUNET_SERVER_Client *client,
390 struct GNUNET_SERVER_Handle *server)
391{
392 struct HostEntry *pos;
393 struct InfoMessage *im;
394 const struct GNUNET_MessageHeader *end;
395 uint16_t hs;
396 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE];
397 struct GNUNET_SERVER_TransmitContext *tc;
398
399 tc = GNUNET_SERVER_transmit_context_create (client);
400 pos = hosts;
401 while (pos != NULL)
402 {
403 if ((only == NULL) ||
404 (0 ==
405 memcmp (only, &pos->identity,
406 sizeof (struct GNUNET_PeerIdentity))))
407 {
408 change_host_trust (&pos->identity, trust_change);
409 hs = 0;
410 im = (struct InfoMessage *) buf;
411 if (pos->hello != NULL)
412 {
413 hs = GNUNET_HELLO_size (pos->hello);
414 GNUNET_assert (hs <
415 GNUNET_SERVER_MAX_MESSAGE_SIZE -
416 sizeof (struct InfoMessage));
417 memcpy (&im[1], pos->hello, hs);
418 }
419 im->trust = htonl (pos->trust);
420 im->peer = pos->identity;
421 end = &im->header;
422 GNUNET_SERVER_transmit_context_append (tc,
423 &end[1],
424 hs +
425 sizeof (struct InfoMessage) -
426 sizeof (struct
427 GNUNET_MessageHeader),
428 GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
429 }
430 pos = pos->next;
431 }
432 GNUNET_SERVER_transmit_context_append (tc, NULL, 0,
433 GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
434 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
435}
436
437
438/**
439 * Write host-trust information to a file - flush the buffer entry!
440 * Assumes synchronized access.
441 */
442static void
443flush_trust (struct HostEntry *host)
444{
445 char *fn;
446 uint32_t trust;
447
448 if (host->trust == host->disk_trust)
449 return; /* unchanged */
450 fn = get_trust_filename (&host->identity);
451 if (host->trust == 0)
452 {
453 if ((0 != UNLINK (fn)) && (errno != ENOENT))
454 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
455 GNUNET_ERROR_TYPE_BULK, "unlink", fn);
456 }
457 else
458 {
459 trust = htonl (host->trust);
460 if (GNUNET_OK ==
461 GNUNET_DISK_file_write (fn, &trust, sizeof (uint32_t), "644"))
462 host->disk_trust = host->trust;
463 }
464 GNUNET_free (fn);
465}
466
467/**
468 * Call this method periodically to scan data/hosts for new hosts.
469 */
470static void
471cron_flush_trust (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
472{
473 struct HostEntry *pos;
474
475 pos = hosts;
476 while (pos != NULL)
477 {
478 flush_trust (pos);
479 pos = pos->next;
480 }
481 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
482 GNUNET_SCHEDULER_add_delayed (tc->sched,
483 GNUNET_YES,
484 GNUNET_SCHEDULER_PRIORITY_KEEP,
485 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
486 TRUST_FLUSH_FREQ, &cron_flush_trust, NULL);
487}
488
489
490/**
491 * @brief delete expired HELLO entries in data/hosts/
492 */
493static int
494discard_hosts_helper (void *cls, const char *fn)
495{
496 struct GNUNET_TIME_Absolute *now = cls;
497 char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
498 const struct GNUNET_HELLO_Message *hello;
499 struct GNUNET_HELLO_Message *new_hello;
500 int size;
501
502 size = GNUNET_DISK_file_read (fn, sizeof (buffer), buffer);
503 if ((size < sizeof (struct GNUNET_MessageHeader)) && (0 != UNLINK (fn)))
504 {
505 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
506 GNUNET_ERROR_TYPE_BULK, "unlink", fn);
507 return GNUNET_OK;
508 }
509 hello = (const struct GNUNET_HELLO_Message *) buffer;
510 new_hello = GNUNET_HELLO_iterate_addresses (hello,
511 GNUNET_YES,
512 &discard_expired, now);
513 if ((new_hello == NULL) && (0 != UNLINK (fn)))
514 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
515 GNUNET_ERROR_TYPE_BULK, "unlink", fn);
516 if (new_hello != NULL)
517 {
518 GNUNET_DISK_file_write (fn,
519 new_hello,
520 GNUNET_HELLO_size (new_hello), "644");
521 GNUNET_free (new_hello);
522 }
523 return GNUNET_OK;
524}
525
526
527/**
528 * Call this method periodically to scan data/hosts for new hosts.
529 */
530static void
531cron_clean_data_hosts (void *cls,
532 const struct GNUNET_SCHEDULER_TaskContext *tc)
533{
534 struct GNUNET_TIME_Absolute now;
535
536 now = GNUNET_TIME_absolute_get ();
537 GNUNET_DISK_directory_scan (networkIdDirectory,
538 &discard_hosts_helper, &now);
539
540 GNUNET_SCHEDULER_add_delayed (tc->sched,
541 GNUNET_NO,
542 GNUNET_SCHEDULER_PRIORITY_KEEP,
543 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
544 DATA_HOST_CLEAN_FREQ,
545 &cron_clean_data_hosts, NULL);
546}
547
548
549/**
550 * Handle ADD-message.
551 *
552 * @param cls closure
553 * @param server the server handling the message
554 * @param client identification of the client
555 * @param message the actual message
556 */
557static void
558handle_add (void *cls,
559 struct GNUNET_SERVER_Handle *server,
560 struct GNUNET_SERVER_Client *client,
561 const struct GNUNET_MessageHeader *message)
562{
563 const struct PeerAddMessage *pam;
564 const struct GNUNET_MessageHeader *hello;
565 uint16_t size;
566
567 size = ntohs (message->size);
568 if (size <
569 sizeof (struct PeerAddMessage) + sizeof (struct GNUNET_MessageHeader))
570 {
571 GNUNET_break (0);
572 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
573 return;
574 }
575 pam = (const struct PeerAddMessage *) message;
576 hello = (const struct GNUNET_MessageHeader *) &pam[1];
577 if (size != sizeof (struct PeerAddMessage) + ntohs (hello->size))
578 {
579 GNUNET_break (0);
580 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
581 return;
582 }
583 bind_address (&pam->peer, (const struct GNUNET_HELLO_Message *) hello);
584 GNUNET_SERVER_receive_done (client, GNUNET_OK);
585}
586
587
588/**
589 * Handle GET-message.
590 *
591 * @param cls closure
592 * @param server the server handling the message
593 * @param client identification of the client
594 * @param message the actual message
595 */
596static void
597handle_get (void *cls,
598 struct GNUNET_SERVER_Handle *server,
599 struct GNUNET_SERVER_Client *client,
600 const struct GNUNET_MessageHeader *message)
601{
602 const struct ListPeerMessage *lpm;
603
604 lpm = (const struct ListPeerMessage *) message;
605 send_to_each_host (&lpm->peer, ntohl (lpm->trust_change), client, server);
606}
607
608
609/**
610 * Handle GET-ALL-message.
611 *
612 * @param cls closure
613 * @param server the server handling the message
614 * @param client identification of the client
615 * @param message the actual message
616 */
617static void
618handle_get_all (void *cls,
619 struct GNUNET_SERVER_Handle *server,
620 struct GNUNET_SERVER_Client *client,
621 const struct GNUNET_MessageHeader *message)
622{
623 const struct ListAllPeersMessage *lpm;
624
625 lpm = (const struct ListAllPeersMessage *) message;
626 send_to_each_host (NULL, ntohl (lpm->trust_change), client, server);
627}
628
629
630/**
631 * List of handlers for the messages understood by this
632 * service.
633 */
634static struct GNUNET_SERVER_MessageHandler handlers[] = {
635 {&handle_add, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_ADD, 0},
636 {&handle_get, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET,
637 sizeof (struct ListPeerMessage)},
638 {&handle_get_all, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL,
639 sizeof (struct ListAllPeersMessage)},
640 {NULL, NULL, 0, 0}
641};
642
643
644/**
645 * Process statistics requests.
646 *
647 * @param cls closure
648 * @param sched scheduler to use
649 * @param server the initialized server
650 * @param cfg configuration to use
651 */
652static void
653run (void *cls,
654 struct GNUNET_SCHEDULER_Handle *sched,
655 struct GNUNET_SERVER_Handle *server,
656 struct GNUNET_CONFIGURATION_Handle *cfg)
657{
658 GNUNET_assert (GNUNET_OK ==
659 GNUNET_CONFIGURATION_get_value_filename (cfg,
660 "peerinfo",
661 "HOSTS",
662 &networkIdDirectory));
663 GNUNET_assert (GNUNET_OK ==
664 GNUNET_CONFIGURATION_get_value_filename (cfg,
665 "peerinfo",
666 "TRUST",
667 &trustDirectory));
668 GNUNET_DISK_directory_create (networkIdDirectory);
669 GNUNET_DISK_directory_create (trustDirectory);
670 GNUNET_SCHEDULER_add_delayed (sched,
671 GNUNET_NO,
672 GNUNET_SCHEDULER_PRIORITY_IDLE,
673 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
674 GNUNET_TIME_UNIT_MILLISECONDS,
675 &cron_scan_directory_data_hosts, NULL);
676 GNUNET_SCHEDULER_add_delayed (sched,
677 GNUNET_YES,
678 GNUNET_SCHEDULER_PRIORITY_HIGH,
679 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
680 TRUST_FLUSH_FREQ, &cron_flush_trust, NULL);
681 GNUNET_SCHEDULER_add_delayed (sched,
682 GNUNET_NO,
683 GNUNET_SCHEDULER_PRIORITY_IDLE,
684 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
685 DATA_HOST_CLEAN_FREQ,
686 &cron_clean_data_hosts, NULL);
687 GNUNET_SERVER_add_handlers (server, handlers);
688}
689
690
691/**
692 * The main function for the statistics service.
693 *
694 * @param argc number of arguments from the command line
695 * @param argv command line arguments
696 * @return 0 ok, 1 on error
697 */
698int
699main (int argc, char *const *argv)
700{
701 return (GNUNET_OK ==
702 GNUNET_SERVICE_run (argc,
703 argv,
704 "peerinfo", &run, NULL, NULL, NULL)) ? 0 : 1;
705}
706
707
708/* end of gnunet-service-peerinfo.c */
diff --git a/src/peerinfo/peerinfo.h b/src/peerinfo/peerinfo.h
new file mode 100644
index 000000000..040b084e4
--- /dev/null
+++ b/src/peerinfo/peerinfo.h
@@ -0,0 +1,135 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file peerinfo/peerinfo.h
23 * @brief common internal definitions for peerinfo service
24 * @author Christian Grothoff
25 */
26#include "gnunet_crypto_lib.h"
27#include "gnunet_time_lib.h"
28#include "gnunet_peerinfo_service.h"
29
30
31/**
32 * Add the given peer to the list. This message
33 * is always followed by a verified HELLO message.
34 */
35struct PeerAddMessage
36{
37
38 /**
39 * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_ADD
40 */
41 struct GNUNET_MessageHeader header;
42
43 /**
44 * Always zero.
45 */
46 uint32_t reserved GNUNET_PACKED;
47
48 /**
49 * For which peer do we provide a HELLO message here?
50 */
51 struct GNUNET_PeerIdentity peer;
52
53};
54
55
56/**
57 * Message requesting a listing of all known peers,
58 * possibly modified by the specified trust value
59 * and restricted to the specified peer identity.
60 */
61struct ListPeerMessage
62{
63
64 /**
65 * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_GET
66 */
67 struct GNUNET_MessageHeader header;
68
69 /**
70 * How much to change the trust in each returned peer,
71 * in network byte order.
72 */
73 int32_t trust_change GNUNET_PACKED;
74
75 /**
76 * Restrict to peers with this identity (optional
77 * field, check header.size!).
78 */
79 struct GNUNET_PeerIdentity peer;
80
81};
82
83
84/**
85 * Message requesting a listing of all known peers,
86 * possibly modified by the specified trust value
87 * and restricted to the specified peer identity.
88 */
89struct ListAllPeersMessage
90{
91
92 /**
93 * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_GET
94 */
95 struct GNUNET_MessageHeader header;
96
97 /**
98 * How much to change the trust in each returned peer,
99 * in network byte order.
100 */
101 int32_t trust_change GNUNET_PACKED;
102
103};
104
105
106/**
107 * Message used to inform the client about
108 * a particular peer; this message is optionally followed
109 * by a HELLO message for the respective peer (if available).
110 * Check the header.size field to see if a HELLO is
111 * present.
112 */
113struct InfoMessage
114{
115
116 /**
117 * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_INFO
118 */
119 struct GNUNET_MessageHeader header;
120
121 /**
122 * Amount of trust we now have in the peer,
123 * in network byte order.
124 */
125 uint32_t trust GNUNET_PACKED;
126
127 /**
128 * About which peer are we talking here?
129 */
130 struct GNUNET_PeerIdentity peer;
131
132};
133
134
135/* end of peerinfo.h */
diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c
new file mode 100644
index 000000000..ba5ade199
--- /dev/null
+++ b/src/peerinfo/peerinfo_api.c
@@ -0,0 +1,302 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2004, 2005, 2007, 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file peerinfo/peerinfo_api.c
23 * @brief API to access peerinfo service
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_client_lib.h"
28#include "gnunet_peerinfo_service.h"
29#include "gnunet_protocols.h"
30#include "gnunet_time_lib.h"
31#include "peerinfo.h"
32
33#define ADD_PEER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
34
35
36struct CAFContext
37{
38 struct GNUNET_CLIENT_Connection *client;
39 struct GNUNET_MessageHeader *msg;
40};
41
42
43static size_t
44copy_and_free (void *cls, size_t size, void *buf)
45{
46 struct CAFContext *cc = cls;
47 struct GNUNET_MessageHeader *msg = cc->msg;
48 uint16_t msize;
49
50 if (buf == NULL)
51 {
52 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
53 _
54 ("Failed to transmit message of type %u to `%s' service.\n"),
55 ntohs (msg->type), "peerinfo");
56 GNUNET_free (msg);
57 GNUNET_CLIENT_disconnect (cc->client);
58 GNUNET_free (cc);
59 return 0;
60 }
61 msize = ntohs (msg->size);
62 GNUNET_assert (size >= msize);
63 memcpy (buf, msg, msize);
64 GNUNET_free (msg);
65 GNUNET_CLIENT_disconnect (cc->client);
66 GNUNET_free (cc);
67 return msize;
68}
69
70
71
72/**
73 * Add a host to the persistent list.
74 *
75 * @param cfg configuration to use
76 * @param sched scheduler to use
77 * @param peer identity of the peer
78 * @param hello the verified (!) HELLO message
79 * @param expiration when the HELLO will expire
80 */
81void
82GNUNET_PEERINFO_add_peer (struct GNUNET_CONFIGURATION_Handle *cfg,
83 struct GNUNET_SCHEDULER_Handle *sched,
84 const struct GNUNET_PeerIdentity *peer,
85 const struct GNUNET_HELLO_Message *hello)
86{
87 struct GNUNET_CLIENT_Connection *client;
88 struct PeerAddMessage *pam;
89 uint16_t hs;
90 struct CAFContext *cc;
91
92 client = GNUNET_CLIENT_connect (sched, "peerinfo", cfg);
93 if (client == NULL)
94 {
95 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
96 _("Could not connect to `%s' service.\n"), "peerinfo");
97 return;
98 }
99 hs = GNUNET_HELLO_size (hello);
100 pam = GNUNET_malloc (sizeof (struct PeerAddMessage) + hs);
101 pam->header.size = htons (hs + sizeof (struct PeerAddMessage));
102 pam->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_ADD);
103 memcpy (&pam->peer, peer, sizeof (struct GNUNET_PeerIdentity));
104 memcpy (&pam[1], hello, hs);
105 cc = GNUNET_malloc (sizeof (struct CAFContext));
106 cc->client = client;
107 cc->msg = &pam->header;
108 GNUNET_CLIENT_notify_transmit_ready (client,
109 ntohs (pam->header.size),
110 ADD_PEER_TIMEOUT, &copy_and_free, cc);
111}
112
113
114/**
115 * Context for the info handler.
116 */
117struct InfoContext
118{
119
120 /**
121 * Our connection to the PEERINFO service.
122 */
123 struct GNUNET_CLIENT_Connection *client;
124
125 /**
126 * Function to call with information.
127 */
128 GNUNET_PEERINFO_Processor callback;
129
130 /**
131 * Closure for callback.
132 */
133 void *callback_cls;
134
135 /**
136 * When should we time out?
137 */
138 struct GNUNET_TIME_Absolute timeout;
139
140};
141
142
143/**
144 * Type of a function to call when we receive a message
145 * from the service.
146 *
147 * @param cls closure
148 * @param msg message received, NULL on timeout or fatal error
149 */
150static void
151info_handler (void *cls, const struct GNUNET_MessageHeader *msg)
152{
153 struct InfoContext *ic = cls;
154 const struct InfoMessage *im;
155 const struct GNUNET_HELLO_Message *hello;
156 uint16_t ms;
157
158 if (msg == NULL)
159 {
160 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
161 _("Failed to receive response from `%s' service.\n"),
162 "peerinfo");
163 ic->callback (ic->callback_cls, NULL, NULL, 1);
164 GNUNET_CLIENT_disconnect (ic->client);
165 GNUNET_free (ic);
166 return;
167 }
168 if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END)
169 {
170 ic->callback (ic->callback_cls, NULL, NULL, 0);
171 GNUNET_CLIENT_disconnect (ic->client);
172 GNUNET_free (ic);
173 return;
174 }
175 ms = ntohs (msg->size);
176 if ((ms < sizeof (struct InfoMessage)) ||
177 (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_PEERINFO_INFO))
178 {
179 GNUNET_break (0);
180 ic->callback (ic->callback_cls, NULL, NULL, 2);
181 GNUNET_CLIENT_disconnect (ic->client);
182 GNUNET_free (ic);
183 return;
184 }
185 im = (const struct InfoMessage *) msg;
186 hello = NULL;
187 if (ms > sizeof (struct InfoMessage) + sizeof (struct GNUNET_MessageHeader))
188 {
189 hello = (const struct GNUNET_HELLO_Message *) &im[1];
190 if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello))
191 {
192 GNUNET_break (0);
193 ic->callback (ic->callback_cls, NULL, NULL, 2);
194 GNUNET_CLIENT_disconnect (ic->client);
195 GNUNET_free (ic);
196 return;
197 }
198 }
199 ic->callback (ic->callback_cls, &im->peer, hello, ntohl (im->trust));
200 GNUNET_CLIENT_receive (ic->client,
201 &info_handler,
202 ic,
203 GNUNET_TIME_absolute_get_remaining (ic->timeout));
204}
205
206
207static size_t
208copy_then_receive (void *cls, size_t size, void *buf)
209{
210 struct InfoContext *ic = cls;
211 const struct GNUNET_MessageHeader *msg =
212 (const struct GNUNET_MessageHeader *) &ic[1];
213 uint16_t msize;
214
215 if (buf == NULL)
216 {
217 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
218 _
219 ("Failed to transmit message of type %u to `%s' service.\n"),
220 ntohs (msg->type), "peerinfo");
221 ic->callback (ic->callback_cls, NULL, NULL, 1);
222 GNUNET_CLIENT_disconnect (ic->client);
223 GNUNET_free (ic);
224 return 0;
225 }
226 msize = ntohs (msg->size);
227 GNUNET_assert (size >= msize);
228 memcpy (buf, msg, msize);
229 GNUNET_CLIENT_receive (ic->client,
230 &info_handler,
231 ic,
232 GNUNET_TIME_absolute_get_remaining (ic->timeout));
233 return msize;
234}
235
236
237/**
238 * Call a method for each known matching host and change
239 * its trust value. The method will be invoked once for
240 * each host and then finally once with a NULL pointer.
241 * Note that the last call can be triggered by timeout or
242 * by simply being done; however, the trust argument will
243 * be set to zero if we are done and to 1 if we timed out.
244 *
245 * @param cfg configuration to use
246 * @param sched scheduler to use
247 * @param peer restrict iteration to this peer only (can be NULL)
248 * @param trust_delta how much to change the trust in all matching peers
249 * @param timeout how long to wait until timing out
250 * @param callback the method to call for each peer
251 * @param callback_cls closure for callback
252 */
253void
254GNUNET_PEERINFO_for_all (struct GNUNET_CONFIGURATION_Handle *cfg,
255 struct GNUNET_SCHEDULER_Handle *sched,
256 const struct GNUNET_PeerIdentity *peer,
257 int trust_delta,
258 struct GNUNET_TIME_Relative timeout,
259 GNUNET_PEERINFO_Processor callback,
260 void *callback_cls)
261{
262 struct GNUNET_CLIENT_Connection *client;
263 struct ListAllPeersMessage *lapm;
264 struct ListPeerMessage *lpm;
265 size_t hs;
266 struct InfoContext *ihc;
267
268 client = GNUNET_CLIENT_connect (sched, "peerinfo", cfg);
269 if (client == NULL)
270 {
271 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
272 _("Could not connect to `%s' service.\n"), "peerinfo");
273 callback (callback_cls, NULL, NULL, 2);
274 return;
275 }
276 ihc = GNUNET_malloc (sizeof (struct InfoContext) +
277 sizeof (struct ListPeerMessage));
278 ihc->client = client;
279 ihc->callback = callback;
280 ihc->callback_cls = callback_cls;
281 ihc->timeout = GNUNET_TIME_relative_to_absolute (timeout);
282 hs = 0;
283 if (peer == NULL)
284 {
285 lapm = (struct ListAllPeersMessage *) &ihc[1];
286 lapm->header.size = htons (hs = sizeof (struct ListAllPeersMessage));
287 lapm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
288 lapm->trust_change = htonl (trust_delta);
289 }
290 else
291 {
292 lpm = (struct ListPeerMessage *) &ihc[1];
293 lpm->header.size = htons (hs = sizeof (struct ListPeerMessage));
294 lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET);
295 lpm->trust_change = htonl (trust_delta);
296 memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity));
297 }
298 GNUNET_CLIENT_notify_transmit_ready (client,
299 hs, timeout, &copy_then_receive, ihc);
300}
301
302/* end of peerinfo_api.c */
diff --git a/src/peerinfo/test_peerinfo_api.c b/src/peerinfo/test_peerinfo_api.c
new file mode 100644
index 000000000..e7d632fd5
--- /dev/null
+++ b/src/peerinfo/test_peerinfo_api.c
@@ -0,0 +1,175 @@
1/*
2 This file is part of GNUnet.
3 (C) 2004, 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file peerinfo/test_peerinfo_api.c
23 * @brief testcase for peerinfo_api.c
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - test merging of HELLOs (add same peer twice...)
28 */
29
30#include "platform.h"
31#include "gnunet_hello_lib.h"
32#include "gnunet_getopt_lib.h"
33#include "gnunet_os_lib.h"
34#include "gnunet_peerinfo_service.h"
35#include "gnunet_program_lib.h"
36#include "gnunet_time_lib.h"
37
38
39static int
40check_it (void *cls,
41 const char *tname,
42 struct GNUNET_TIME_Absolute expiration,
43 const void *addr, size_t addrlen)
44{
45 unsigned int *agc = cls;
46
47 if (addrlen > 0)
48 {
49 GNUNET_assert (0 == strcmp ("peerinfotest", tname));
50 GNUNET_assert (0 == strncmp ("Address", addr, addrlen));
51 (*agc) -= (1 << (addrlen - 1));
52 }
53 return GNUNET_OK;
54}
55
56
57static void
58process (void *cls,
59 const struct GNUNET_PeerIdentity *peer,
60 const struct GNUNET_HELLO_Message *hello, uint32_t trust)
61{
62 int *ok = cls;
63 unsigned int agc;
64
65 if (peer == NULL)
66 {
67 GNUNET_assert (peer == NULL);
68 GNUNET_assert (2 == *ok);
69 GNUNET_assert (trust == 0);
70 *ok = 0;
71 return;
72 }
73
74 if (hello != NULL)
75 {
76 GNUNET_assert (3 == *ok);
77 agc = 3;
78 GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &check_it, &agc);
79 GNUNET_assert (agc == 0);
80 *ok = 2;
81 }
82}
83
84
85static size_t
86address_generator (void *cls, size_t max, void *buf)
87{
88 size_t *agc = cls;
89 size_t ret;
90
91 if (0 == *agc)
92 return 0;
93 ret = GNUNET_HELLO_add_address ("peerinfotest",
94 GNUNET_TIME_relative_to_absolute
95 (GNUNET_TIME_UNIT_HOURS), "Address", *agc,
96 buf, max);
97 (*agc)--;
98 return ret;
99}
100
101
102static void
103run (void *cls,
104 struct GNUNET_SCHEDULER_Handle *sched,
105 char *const *args,
106 const char *cfgfile, struct GNUNET_CONFIGURATION_Handle *cfg)
107{
108 struct GNUNET_HELLO_Message *hello;
109 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
110 size_t agc;
111 struct GNUNET_PeerIdentity pid;
112
113 memset (&pkey, 32, sizeof (pkey));
114 GNUNET_CRYPTO_hash (&pkey, sizeof (pkey), &pid.hashPubKey);
115 agc = 2;
116 hello = GNUNET_HELLO_create (&pkey, &address_generator, &agc);
117 GNUNET_assert (hello != NULL);
118 GNUNET_PEERINFO_add_peer (cfg, sched, &pid, hello);
119 GNUNET_PEERINFO_for_all (cfg,
120 sched,
121 NULL,
122 0,
123 GNUNET_TIME_relative_multiply
124 (GNUNET_TIME_UNIT_SECONDS, 15), &process, cls);
125 GNUNET_free (hello);
126}
127
128
129static int
130check ()
131{
132 int ok = 3;
133 pid_t pid;
134 char *const argv[] = { "test-peerinfo-api",
135 "-c",
136 "test_peerinfo_api_data.conf",
137#if DEBUG_PEERINFO
138 "-L", "DEBUG",
139#endif
140 NULL
141 };
142 struct GNUNET_GETOPT_CommandLineOption options[] = {
143 GNUNET_GETOPT_OPTION_END
144 };
145 pid = GNUNET_OS_start_process ("gnunet-service-peerinfo",
146 "gnunet-service-peerinfo",
147#if DEBUG_PEERINFO
148 "-L", "DEBUG",
149#endif
150 "-c", "test_peerinfo_api_data.conf", NULL);
151 sleep (1);
152 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
153 argv, "test-peerinfo-api", "nohelp",
154 options, &run, &ok);
155 if (0 != PLIBC_KILL (pid, SIGTERM))
156 {
157 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
158 ok = 1;
159 }
160 waitpid (pid, NULL, 0);
161 return ok;
162}
163
164
165int
166main (int argc, char *argv[])
167{
168 int ret = 0;
169
170 ret = check ();
171
172 return ret;
173}
174
175/* end of test_peerinfo_api.c */
diff --git a/src/peerinfo/test_peerinfo_api_data.conf b/src/peerinfo/test_peerinfo_api_data.conf
new file mode 100644
index 000000000..a81ffccb9
--- /dev/null
+++ b/src/peerinfo/test_peerinfo_api_data.conf
@@ -0,0 +1,5 @@
1[PATHS]
2SERVICEHOME = /tmp/test-gnunetd-peerinfo/
3
4[peerinfo]
5PORT = 22354