aboutsummaryrefslogtreecommitdiff
path: root/src/peerinfo
diff options
context:
space:
mode:
Diffstat (limited to 'src/peerinfo')
-rw-r--r--src/peerinfo/.gitignore6
-rw-r--r--src/peerinfo/Makefile.am105
-rw-r--r--src/peerinfo/gnunet-service-peerinfo.c1370
-rw-r--r--src/peerinfo/peerinfo.conf.in31
-rw-r--r--src/peerinfo/peerinfo.h123
-rw-r--r--src/peerinfo/peerinfo_api.c580
-rw-r--r--src/peerinfo/peerinfo_api_notify.c291
-rw-r--r--src/peerinfo/perf_peerinfo_api.c193
-rw-r--r--src/peerinfo/test_peerinfo_api.c172
-rw-r--r--src/peerinfo/test_peerinfo_api_data.conf15
-rw-r--r--src/peerinfo/test_peerinfo_api_friend_only.c172
-rw-r--r--src/peerinfo/test_peerinfo_api_notify_friend_only.c261
-rw-r--r--src/peerinfo/test_peerinfo_shipped_hellos.c144
13 files changed, 0 insertions, 3463 deletions
diff --git a/src/peerinfo/.gitignore b/src/peerinfo/.gitignore
deleted file mode 100644
index 152ca2916..000000000
--- a/src/peerinfo/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
1gnunet-service-peerinfo
2test_peerinfo_api
3test_peerinfo_api_friend_only
4test_peerinfo_api_notify_friend_only
5test_peerinfo_shipped_hellos
6perf_peerinfo_api
diff --git a/src/peerinfo/Makefile.am b/src/peerinfo/Makefile.am
deleted file mode 100644
index cdab22a9d..000000000
--- a/src/peerinfo/Makefile.am
+++ /dev/null
@@ -1,105 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4pkgcfgdir= $(pkgdatadir)/config.d/
5
6libexecdir= $(pkglibdir)/libexec/
7
8plugindir = $(libdir)/gnunet
9
10pkgcfg_DATA = \
11 peerinfo.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = --coverage -O0
15 XLIB = -lgcov
16endif
17
18lib_LTLIBRARIES = libgnunetpeerinfo.la
19
20
21libgnunetpeerinfo_la_SOURCES = \
22 peerinfo_api.c peerinfo.h \
23 peerinfo_api_notify.c
24libgnunetpeerinfo_la_LIBADD = \
25 $(top_builddir)/src/hello/libgnunethello.la \
26 $(top_builddir)/src/util/libgnunetutil.la \
27 $(XLIB) \
28 $(LTLIBINTL)
29libgnunetpeerinfo_la_LDFLAGS = \
30 $(GN_LIB_LDFLAGS) \
31 -version-info 0:0:0
32
33
34libexec_PROGRAMS = \
35 gnunet-service-peerinfo
36
37gnunet_service_peerinfo_SOURCES = \
38 gnunet-service-peerinfo.c
39gnunet_service_peerinfo_LDADD = \
40 $(top_builddir)/src/hello/libgnunethello.la \
41 $(top_builddir)/src/statistics/libgnunetstatistics.la \
42 $(top_builddir)/src/util/libgnunetutil.la
43gnunet_service_peerinfo_LDFLAGS = \
44 $(GN_LIBINTL)
45
46if HAVE_BENCHMARKS
47 PEERINFO_BENCHMARKS = \
48 perf_peerinfo_api
49endif
50
51check_PROGRAMS = \
52 test_peerinfo_shipped_hellos \
53 test_peerinfo_api \
54 test_peerinfo_api_friend_only \
55 test_peerinfo_api_notify_friend_only \
56 $(PEERINFO_BENCHMARKS)
57
58
59if ENABLE_TEST_RUN
60AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
61TESTS = $(check_PROGRAMS)
62endif
63
64test_peerinfo_shipped_hellos_SOURCES = \
65 test_peerinfo_shipped_hellos.c
66test_peerinfo_shipped_hellos_LDADD = \
67 $(top_builddir)/src/hello/libgnunethello.la \
68 libgnunetpeerinfo.la \
69 $(top_builddir)/src/testing/libgnunettesting.la \
70 $(top_builddir)/src/util/libgnunetutil.la
71
72test_peerinfo_api_SOURCES = \
73 test_peerinfo_api.c
74test_peerinfo_api_LDADD = \
75 $(top_builddir)/src/hello/libgnunethello.la \
76 libgnunetpeerinfo.la \
77 $(top_builddir)/src/testing/libgnunettesting.la \
78 $(top_builddir)/src/util/libgnunetutil.la
79
80test_peerinfo_api_friend_only_SOURCES = \
81 test_peerinfo_api_friend_only.c
82test_peerinfo_api_friend_only_LDADD = \
83 $(top_builddir)/src/hello/libgnunethello.la \
84 libgnunetpeerinfo.la \
85 $(top_builddir)/src/testing/libgnunettesting.la \
86 $(top_builddir)/src/util/libgnunetutil.la
87
88test_peerinfo_api_notify_friend_only_SOURCES = \
89 test_peerinfo_api_notify_friend_only.c
90test_peerinfo_api_notify_friend_only_LDADD = \
91 $(top_builddir)/src/hello/libgnunethello.la \
92 libgnunetpeerinfo.la \
93 $(top_builddir)/src/testing/libgnunettesting.la \
94 $(top_builddir)/src/util/libgnunetutil.la
95
96perf_peerinfo_api_SOURCES = \
97 perf_peerinfo_api.c
98perf_peerinfo_api_LDADD = \
99 $(top_builddir)/src/hello/libgnunethello.la \
100 libgnunetpeerinfo.la \
101 $(top_builddir)/src/testing/libgnunettesting.la \
102 $(top_builddir)/src/util/libgnunetutil.la
103
104EXTRA_DIST = \
105 test_peerinfo_api_data.conf
diff --git a/src/peerinfo/gnunet-service-peerinfo.c b/src/peerinfo/gnunet-service-peerinfo.c
deleted file mode 100644
index 1b1232ecb..000000000
--- a/src/peerinfo/gnunet-service-peerinfo.c
+++ /dev/null
@@ -1,1370 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
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/).
27 *
28 * @author Christian Grothoff
29 */
30
31#include "platform.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_hello_lib.h"
34#include "gnunet_protocols.h"
35#include "gnunet_statistics_service.h"
36#include "peerinfo.h"
37
38/**
39 * How often do we scan the HOST_DIR for new entries?
40 */
41#define DATA_HOST_FREQ \
42 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
43
44/**
45 * How often do we discard old entries in data/hosts/?
46 */
47#define DATA_HOST_CLEAN_FREQ \
48 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60)
49
50
51/**
52 * In-memory cache of known hosts.
53 */
54struct HostEntry
55{
56 /**
57 * Identity of the peer.
58 */
59 struct GNUNET_PeerIdentity identity;
60
61 /**
62 * Hello for the peer (can be NULL)
63 */
64 struct GNUNET_HELLO_Message *hello;
65
66 /**
67 * Friend only hello for the peer (can be NULL)
68 */
69 struct GNUNET_HELLO_Message *friend_only_hello;
70};
71
72
73/**
74 * Result of reading a file
75 */
76struct ReadHostFileContext
77{
78 /**
79 * Hello for the peer (can be NULL)
80 */
81 struct GNUNET_HELLO_Message *hello;
82
83 /**
84 * Friend only hello for the peer (can be NULL)
85 */
86 struct GNUNET_HELLO_Message *friend_only_hello;
87};
88
89
90/**
91 * The in-memory list of known hosts, mapping of
92 * host IDs to 'struct HostEntry*' values.
93 */
94static struct GNUNET_CONTAINER_MultiPeerMap *hostmap;
95
96/**
97 * Clients to immediately notify about all changes.
98 */
99static struct GNUNET_NotificationContext *notify_list;
100
101/**
102 * Clients to immediately notify about all changes,
103 * even for friend-only HELLOs.
104 */
105static struct GNUNET_NotificationContext *notify_friend_only_list;
106
107/**
108 * Directory where the hellos are stored in (peerinfo/)
109 */
110static char *networkIdDirectory;
111
112/**
113 * Handle for reporting statistics.
114 */
115static struct GNUNET_STATISTICS_Handle *stats;
116
117/**
118 * Handle for task to run #cron_clean_data_hosts()
119 */
120static struct GNUNET_SCHEDULER_Task *cron_clean;
121
122/**
123 * Handle for task to run #cron_scan_directory_data_hosts()
124 */
125static struct GNUNET_SCHEDULER_Task *cron_scan;
126
127
128/**
129 * Notify all clients in the notify list about the
130 * given host entry changing.
131 *
132 * @param he entry of the host for which we generate a notification
133 * @param include_friend_only create public of friend-only message
134 * @return generated notification message
135 */
136static struct InfoMessage *
137make_info_message (const struct HostEntry *he, int include_friend_only)
138{
139 struct InfoMessage *im;
140 struct GNUNET_HELLO_Message *src;
141 size_t hs;
142
143 if (GNUNET_YES == include_friend_only)
144 src = he->friend_only_hello;
145 else
146 src = he->hello;
147 hs = (NULL == src) ? 0 : GNUNET_HELLO_size (src);
148 im = GNUNET_malloc (sizeof(struct InfoMessage) + hs);
149 im->header.size = htons (hs + sizeof(struct InfoMessage));
150 im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
151 im->peer = he->identity;
152 GNUNET_memcpy (&im[1], src, hs);
153 return im;
154}
155
156
157/**
158 * Address iterator that causes expired entries to be discarded.
159 *
160 * @param cls pointer to the current time
161 * @param address the address
162 * @param expiration expiration time for the address
163 * @return #GNUNET_NO if expiration smaller than the current time
164 */
165static int
166discard_expired (void *cls,
167 const struct GNUNET_HELLO_Address *address,
168 struct GNUNET_TIME_Absolute expiration)
169{
170 const struct GNUNET_TIME_Absolute *now = cls;
171
172 if (now->abs_value_us > expiration.abs_value_us)
173 {
174 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
175 _ ("Removing expired address of transport `%s'\n"),
176 address->transport_name);
177 return GNUNET_NO;
178 }
179 return GNUNET_OK;
180}
181
182
183/**
184 * Address iterator that counts the remaining addresses.
185 *
186 * @param cls pointer to the counter
187 * @param address the address
188 * @param expiration expiration time for the address
189 * @return #GNUNET_OK (always)
190 */
191static int
192count_addresses (void *cls,
193 const struct GNUNET_HELLO_Address *address,
194 struct GNUNET_TIME_Absolute expiration)
195{
196 unsigned int *cnt = cls;
197
198 (void) address;
199 (void) expiration;
200 (*cnt)++;
201 return GNUNET_OK;
202}
203
204
205/**
206 * Get the filename under which we would store the GNUNET_HELLO_Message
207 * for the given host and protocol.
208 *
209 * @param id peer for which we need the filename for the HELLO
210 * @return filename of the form DIRECTORY/HOSTID
211 */
212static char *
213get_host_filename (const struct GNUNET_PeerIdentity *id)
214{
215 char *fn;
216
217 if (NULL == networkIdDirectory)
218 return NULL;
219 GNUNET_asprintf (&fn,
220 "%s%s%s",
221 networkIdDirectory,
222 DIR_SEPARATOR_STR,
223 GNUNET_i2s_full (id));
224 return fn;
225}
226
227
228/**
229 * Broadcast information about the given entry to all
230 * clients that care.
231 *
232 * @param entry entry to broadcast about
233 */
234static void
235notify_all (struct HostEntry *entry)
236{
237 struct InfoMessage *msg_pub;
238 struct InfoMessage *msg_friend;
239
240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
241 "Notifying all clients about peer `%s'\n",
242 GNUNET_i2s (&entry->identity));
243 msg_pub = make_info_message (entry, GNUNET_NO);
244 GNUNET_notification_context_broadcast (notify_list,
245 &msg_pub->header,
246 GNUNET_NO);
247 GNUNET_free (msg_pub);
248 msg_friend = make_info_message (entry, GNUNET_YES);
249 GNUNET_notification_context_broadcast (notify_friend_only_list,
250 &msg_friend->header,
251 GNUNET_NO);
252 GNUNET_free (msg_friend);
253}
254
255
256/**
257 * Bind a host address (hello) to a hostId.
258 *
259 * @param peer the peer for which this is a hello
260 * @param hello the verified (!) hello message
261 */
262static void
263update_hello (const struct GNUNET_PeerIdentity *peer,
264 const struct GNUNET_HELLO_Message *hello);
265
266
267/**
268 * Try to read the HELLOs in the given filename and discard expired
269 * addresses. Removes the file if one the HELLO is malformed. If all
270 * addresses are expired, the HELLO is also removed (but the HELLO
271 * with the public key is still returned if it was found and valid).
272 * The file can contain multiple HELLO messages.
273 *
274 * @param fn name of the file
275 * @param unlink_garbage if #GNUNET_YES, try to remove useless files
276 * @param r ReadHostFileContext to store the resutl
277 */
278static void
279read_host_file (const char *fn,
280 int unlink_garbage,
281 struct ReadHostFileContext *r)
282{
283 char buffer[GNUNET_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
284 ssize_t size_total;
285 struct GNUNET_TIME_Absolute now;
286 unsigned int left;
287 const struct GNUNET_HELLO_Message *hello;
288 struct GNUNET_HELLO_Message *hello_clean;
289 size_t read_pos;
290 uint16_t size_hello;
291
292 r->friend_only_hello = NULL;
293 r->hello = NULL;
294
295 if (GNUNET_YES != GNUNET_DISK_file_test (fn))
296 return;
297 size_total = GNUNET_DISK_fn_read (fn, buffer, sizeof(buffer));
298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
299 "Read %d bytes from `%s'\n",
300 (int) size_total,
301 fn);
302 if ((size_total < 0) ||
303 (((size_t) size_total) < sizeof(struct GNUNET_MessageHeader)))
304 {
305 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
306 _ ("Failed to parse HELLO in file `%s': %s\n"),
307 fn,
308 "File has invalid size");
309 if ((GNUNET_YES == unlink_garbage) && (0 != unlink (fn)) &&
310 (ENOENT != errno))
311 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
312 return;
313 }
314
315 read_pos = 0;
316 while (read_pos < (size_t) size_total)
317 {
318 hello = (const struct GNUNET_HELLO_Message *) &buffer[read_pos];
319 size_hello = GNUNET_HELLO_size (hello);
320 if ((0 == size_hello) || (((size_t) size_total) - read_pos < size_hello))
321 {
322 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
323 _ ("Failed to parse HELLO in file `%s'\n"),
324 fn);
325 if (0 == read_pos)
326 {
327 if ((GNUNET_YES == unlink_garbage) && (0 != unlink (fn)) &&
328 (ENOENT != errno))
329 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
330 }
331 else
332 {
333 if ((GNUNET_YES == unlink_garbage) && (0 != truncate (fn, read_pos)) &&
334 (ENOENT != errno))
335 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "truncate", fn);
336 }
337 return;
338 }
339
340 now = GNUNET_TIME_absolute_get ();
341 hello_clean = GNUNET_HELLO_iterate_addresses (hello,
342 GNUNET_YES,
343 &discard_expired,
344 &now);
345 if (NULL == hello_clean)
346 {
347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
348 _ ("Failed to parse HELLO in file `%s'\n"),
349 fn);
350 if ((GNUNET_YES == unlink_garbage) && (0 != unlink (fn)) &&
351 (ENOENT != errno))
352 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
353 return;
354 }
355 left = 0;
356 (void) GNUNET_HELLO_iterate_addresses (hello_clean,
357 GNUNET_NO,
358 &count_addresses,
359 &left);
360
361 if (0 == left)
362 {
363 GNUNET_free (hello_clean);
364 break;
365 }
366
367 if (GNUNET_NO == GNUNET_HELLO_is_friend_only (hello_clean))
368 {
369 if (NULL == r->hello)
370 r->hello = hello_clean;
371 else
372 {
373 GNUNET_break (0);
374 GNUNET_free (r->hello);
375 r->hello = hello_clean;
376 }
377 }
378 else
379 {
380 if (NULL == r->friend_only_hello)
381 r->friend_only_hello = hello_clean;
382 else
383 {
384 GNUNET_break (0);
385 GNUNET_free (r->friend_only_hello);
386 r->friend_only_hello = hello_clean;
387 }
388 }
389 read_pos += size_hello;
390 }
391
392 if (0 == left)
393 {
394 /* no addresses left, remove from disk */
395 if ((GNUNET_YES == unlink_garbage) && (0 != unlink (fn)))
396 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
397 }
398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
399 "Found `%s' and `%s' HELLO message in file\n",
400 (NULL != r->hello) ? "public" : "NON-public",
401 (NULL != r->friend_only_hello) ? "friend only"
402 : "NO friend only");
403}
404
405
406/**
407 * Add a host to the list and notify clients about this event
408 *
409 * @param identity the identity of the host
410 * @return the HostEntry
411 */
412static struct HostEntry *
413add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
414{
415 struct HostEntry *entry;
416 struct ReadHostFileContext r;
417 char *fn;
418
419 entry = GNUNET_CONTAINER_multipeermap_get (hostmap, identity);
420 if (NULL == entry)
421 {
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
423 "Adding new peer `%s'\n",
424 GNUNET_i2s (identity));
425 GNUNET_STATISTICS_update (stats,
426 gettext_noop ("# peers known"),
427 1,
428 GNUNET_NO);
429 entry = GNUNET_new (struct HostEntry);
430 entry->identity = *identity;
431 GNUNET_assert (GNUNET_OK ==
432 GNUNET_CONTAINER_multipeermap_put (
433 hostmap,
434 &entry->identity,
435 entry,
436 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
437 notify_all (entry);
438 fn = get_host_filename (identity);
439 if (NULL != fn)
440 {
441 read_host_file (fn, GNUNET_YES, &r);
442 if (NULL != r.hello)
443 update_hello (identity, r.hello);
444 if (NULL != r.friend_only_hello)
445 update_hello (identity, r.friend_only_hello);
446 GNUNET_free (r.hello);
447 GNUNET_free (r.friend_only_hello);
448 GNUNET_free (fn);
449 }
450 }
451 return entry;
452}
453
454
455/**
456 * Remove a file that should not be there. LOG
457 * success or failure.
458 *
459 * @param fullname name of the file to remove
460 */
461static void
462remove_garbage (const char *fullname)
463{
464 if (0 == unlink (fullname))
465 GNUNET_log (
466 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
467 _ (
468 "File `%s' in directory `%s' does not match naming convention. Removed.\n"),
469 fullname,
470 networkIdDirectory);
471 else
472 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
473 "unlink",
474 fullname);
475}
476
477
478/**
479 * Closure for #hosts_directory_scan_callback().
480 */
481struct DirScanContext
482{
483 /**
484 * #GNUNET_YES if we should remove files that are broken,
485 * #GNUNET_NO if the directory we are iterating over should
486 * be treated as read-only by us.
487 */
488 int remove_files;
489
490 /**
491 * Counter for the number of (valid) entries found, incremented
492 * by one for each match.
493 */
494 unsigned int matched;
495};
496
497
498/**
499 * Function that is called on each HELLO file in a particular directory.
500 * Try to parse the file and add the HELLO to our list.
501 *
502 * @param cls pointer to 'unsigned int' to increment for each file, or NULL
503 * if the file is from a read-only, read-once resource directory
504 * @param fullname name of the file to parse
505 * @return #GNUNET_OK (continue iteration)
506 */
507static int
508hosts_directory_scan_callback (void *cls, const char *fullname)
509{
510 struct DirScanContext *dsc = cls;
511 struct GNUNET_PeerIdentity identity;
512 struct ReadHostFileContext r;
513 const char *filename;
514 struct GNUNET_PeerIdentity id_public;
515 struct GNUNET_PeerIdentity id_friend;
516 struct GNUNET_PeerIdentity id;
517
518 if (GNUNET_YES != GNUNET_DISK_file_test (fullname))
519 return GNUNET_OK; /* ignore non-files */
520
521 filename = strrchr (fullname, DIR_SEPARATOR);
522 if ((NULL == filename) || (1 > strlen (filename)))
523 filename = fullname;
524 else
525 filename++;
526
527 read_host_file (fullname, dsc->remove_files, &r);
528 if ((NULL == r.hello) && (NULL == r.friend_only_hello))
529 return GNUNET_OK;
530 if (NULL != r.friend_only_hello)
531 {
532 if (GNUNET_OK != GNUNET_HELLO_get_id (r.friend_only_hello, &id_friend))
533 {
534 if (GNUNET_YES == dsc->remove_files)
535 remove_garbage (fullname);
536 return GNUNET_OK;
537 }
538 id = id_friend;
539 }
540 if (NULL != r.hello)
541 {
542 if (GNUNET_OK != GNUNET_HELLO_get_id (r.hello, &id_public))
543 {
544 if (GNUNET_YES == dsc->remove_files)
545 remove_garbage (fullname);
546 return GNUNET_OK;
547 }
548 id = id_public;
549 }
550
551 if ((NULL != r.hello) && (NULL != r.friend_only_hello) &&
552 (0 != GNUNET_memcmp (&id_friend, &id_public)))
553 {
554 /* HELLOs are not for the same peer */
555 GNUNET_break (0);
556 if (GNUNET_YES == dsc->remove_files)
557 remove_garbage (fullname);
558 return GNUNET_OK;
559 }
560 if (GNUNET_OK ==
561 GNUNET_CRYPTO_eddsa_public_key_from_string (filename,
562 strlen (filename),
563 &identity.public_key))
564 {
565 if (0 != GNUNET_memcmp (&id, &identity))
566 {
567 /* HELLOs are not for the same peer */
568 GNUNET_break (0);
569 if (GNUNET_YES == dsc->remove_files)
570 remove_garbage (fullname);
571 return GNUNET_OK;
572 }
573 }
574
575 /* ok, found something valid, remember HELLO */
576 add_host_to_known_hosts (&id);
577 if (NULL != r.hello)
578 {
579 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
580 "Updating peer `%s' public HELLO \n",
581 GNUNET_i2s (&id));
582 update_hello (&id, r.hello);
583 GNUNET_free (r.hello);
584 }
585 if (NULL != r.friend_only_hello)
586 {
587 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
588 "Updating peer `%s' friend only HELLO \n",
589 GNUNET_i2s (&id));
590 update_hello (&id, r.friend_only_hello);
591 GNUNET_free (r.friend_only_hello);
592 }
593 dsc->matched++;
594 return GNUNET_OK;
595}
596
597
598/**
599 * Call this method periodically to scan data/hosts for new hosts.
600 *
601 * @param cls unused
602 */
603static void
604cron_scan_directory_data_hosts (void *cls)
605{
606 static unsigned int retries;
607 struct DirScanContext dsc;
608
609 (void) cls;
610 cron_scan = NULL;
611 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (networkIdDirectory))
612 {
613 cron_scan =
614 GNUNET_SCHEDULER_add_delayed_with_priority (DATA_HOST_FREQ,
615 GNUNET_SCHEDULER_PRIORITY_IDLE,
616 &
617 cron_scan_directory_data_hosts,
618 NULL);
619 return;
620 }
621 dsc.matched = 0;
622 dsc.remove_files = GNUNET_YES;
623 GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
624 _ ("Scanning directory `%s'\n"),
625 networkIdDirectory);
626 GNUNET_DISK_directory_scan (networkIdDirectory,
627 &hosts_directory_scan_callback,
628 &dsc);
629 if ((0 == dsc.matched) && (0 == (++retries & 31)))
630 GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
631 _ ("Still no peers found in `%s'!\n"),
632 networkIdDirectory);
633 cron_scan =
634 GNUNET_SCHEDULER_add_delayed_with_priority (DATA_HOST_FREQ,
635 GNUNET_SCHEDULER_PRIORITY_IDLE,
636 &cron_scan_directory_data_hosts,
637 NULL);
638}
639
640
641/**
642 * Update the HELLO of a friend by merging the addresses.
643 *
644 * @param hello original hello
645 * @param friend_hello hello with additional addresses
646 * @return merged HELLO
647 */
648static struct GNUNET_HELLO_Message *
649update_friend_hello (const struct GNUNET_HELLO_Message *hello,
650 const struct GNUNET_HELLO_Message *friend_hello)
651{
652 struct GNUNET_HELLO_Message *res;
653 struct GNUNET_HELLO_Message *tmp;
654 struct GNUNET_PeerIdentity pid;
655
656 if (NULL != friend_hello)
657 {
658 res = GNUNET_HELLO_merge (hello, friend_hello);
659 GNUNET_assert (GNUNET_YES == GNUNET_HELLO_is_friend_only (res));
660 return res;
661 }
662
663 if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
664 {
665 GNUNET_break (0);
666 return NULL;
667 }
668 tmp = GNUNET_HELLO_create (&pid.public_key, NULL, NULL, GNUNET_YES);
669 res = GNUNET_HELLO_merge (hello, tmp);
670 GNUNET_free (tmp);
671 GNUNET_assert (GNUNET_YES == GNUNET_HELLO_is_friend_only (res));
672 return res;
673}
674
675
676/**
677 * Bind a host address (hello) to a hostId.
678 *
679 * @param peer the peer for which this is a hello
680 * @param hello the verified (!) hello message
681 */
682static void
683update_hello (const struct GNUNET_PeerIdentity *peer,
684 const struct GNUNET_HELLO_Message *hello)
685{
686 char *fn;
687 struct HostEntry *host;
688 struct GNUNET_HELLO_Message *mrg;
689 struct GNUNET_HELLO_Message **dest;
690 struct GNUNET_TIME_Absolute delta;
691 unsigned int cnt;
692 unsigned int size;
693 int friend_hello_type;
694 int store_hello;
695 int store_friend_hello;
696 unsigned int pos;
697 char *buffer;
698
699 host = GNUNET_CONTAINER_multipeermap_get (hostmap, peer);
700 GNUNET_assert (NULL != host);
701
702 friend_hello_type = GNUNET_HELLO_is_friend_only (hello);
703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
704 "Updating %s HELLO for `%s'\n",
705 (GNUNET_YES == friend_hello_type) ? "friend-only" : "public",
706 GNUNET_i2s (peer));
707
708 dest = NULL;
709 if (GNUNET_YES == friend_hello_type)
710 {
711 dest = &host->friend_only_hello;
712 }
713 else
714 {
715 dest = &host->hello;
716 }
717
718 if (NULL == (*dest))
719 {
720 (*dest) = GNUNET_malloc (GNUNET_HELLO_size (hello));
721 GNUNET_memcpy ((*dest), hello, GNUNET_HELLO_size (hello));
722 }
723 else
724 {
725 mrg = GNUNET_HELLO_merge ((*dest), hello);
726 delta = GNUNET_HELLO_equals (mrg, (*dest), GNUNET_TIME_absolute_get ());
727 if (delta.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
728 {
729 /* no differences, just ignore the update */
730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
731 "No change in %s HELLO for `%s'\n",
732 (GNUNET_YES == friend_hello_type) ? "friend-only" : "public",
733 GNUNET_i2s (peer));
734 GNUNET_free (mrg);
735 return;
736 }
737 GNUNET_free ((*dest));
738 (*dest) = mrg;
739 }
740
741 if ((NULL != (host->hello)) && (GNUNET_NO == friend_hello_type))
742 {
743 /* Update friend only hello */
744 mrg = update_friend_hello (host->hello, host->friend_only_hello);
745 if (NULL != host->friend_only_hello)
746 GNUNET_free (host->friend_only_hello);
747 host->friend_only_hello = mrg;
748 }
749
750 if (NULL != host->hello)
751 GNUNET_assert ((GNUNET_NO == GNUNET_HELLO_is_friend_only (host->hello)));
752 if (NULL != host->friend_only_hello)
753 GNUNET_assert (
754 (GNUNET_YES == GNUNET_HELLO_is_friend_only (host->friend_only_hello)));
755
756 fn = get_host_filename (peer);
757 if ((NULL != fn) && (GNUNET_OK == GNUNET_DISK_directory_create_for_file (fn)))
758 {
759 store_hello = GNUNET_NO;
760 size = 0;
761 cnt = 0;
762 if (NULL != host->hello)
763 (void) GNUNET_HELLO_iterate_addresses (host->hello,
764 GNUNET_NO,
765 &count_addresses,
766 &cnt);
767 if (cnt > 0)
768 {
769 store_hello = GNUNET_YES;
770 size += GNUNET_HELLO_size (host->hello);
771 }
772 cnt = 0;
773 if (NULL != host->friend_only_hello)
774 (void) GNUNET_HELLO_iterate_addresses (host->friend_only_hello,
775 GNUNET_NO,
776 &count_addresses,
777 &cnt);
778 store_friend_hello = GNUNET_NO;
779 if (0 < cnt)
780 {
781 store_friend_hello = GNUNET_YES;
782 size += GNUNET_HELLO_size (host->friend_only_hello);
783 }
784
785 if ((GNUNET_NO == store_hello) && (GNUNET_NO == store_friend_hello))
786 {
787 /* no valid addresses, don't put HELLO on disk; in fact,
788 if one exists on disk, remove it */
789 (void) unlink (fn);
790 }
791 else
792 {
793 buffer = GNUNET_malloc (size);
794 pos = 0;
795
796 if (GNUNET_YES == store_hello)
797 {
798 GNUNET_memcpy (buffer, host->hello, GNUNET_HELLO_size (host->hello));
799 pos += GNUNET_HELLO_size (host->hello);
800 }
801 if (GNUNET_YES == store_friend_hello)
802 {
803 GNUNET_memcpy (&buffer[pos],
804 host->friend_only_hello,
805 GNUNET_HELLO_size (host->friend_only_hello));
806 pos += GNUNET_HELLO_size (host->friend_only_hello);
807 }
808 GNUNET_assert (pos == size);
809
810 if (GNUNET_SYSERR ==
811 GNUNET_DISK_fn_write (fn,
812 buffer,
813 size,
814 GNUNET_DISK_PERM_USER_READ
815 | GNUNET_DISK_PERM_USER_WRITE
816 | GNUNET_DISK_PERM_GROUP_READ
817 | GNUNET_DISK_PERM_OTHER_READ))
818 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn);
819 else
820 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
821 "Stored %s %s HELLO in %s with total size %u\n",
822 (GNUNET_YES == store_friend_hello) ? "friend-only" : "",
823 (GNUNET_YES == store_hello) ? "public" : "",
824 fn,
825 size);
826 GNUNET_free (buffer);
827 }
828 }
829 GNUNET_free (fn);
830 notify_all (host);
831}
832
833
834/**
835 * Closure for #add_to_tc()
836 */
837struct TransmitContext
838{
839 /**
840 * Client to transmit to
841 */
842 struct GNUNET_SERVICE_Client *client;
843
844 /**
845 * Include friend only HELLOs #GNUNET_YES or #GNUNET_NO
846 */
847 int friend_only;
848};
849
850
851/**
852 * Do transmit info about peer to given host.
853 *
854 * @param cls NULL to hit all hosts, otherwise specifies a particular target
855 * @param key hostID
856 * @param value information to transmit
857 * @return #GNUNET_YES (continue to iterate)
858 */
859static int
860add_to_tc (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
861{
862 struct TransmitContext *tc = cls;
863 struct HostEntry *pos = value;
864 struct InfoMessage *im;
865 uint16_t hs;
866 struct GNUNET_MQ_Envelope *env;
867
868 hs = 0;
869
870 if ((NULL != pos->hello) && (GNUNET_NO == tc->friend_only))
871 {
872 /* Copy public HELLO */
873 hs = GNUNET_HELLO_size (pos->hello);
874 GNUNET_assert (hs < GNUNET_MAX_MESSAGE_SIZE - sizeof(struct InfoMessage));
875 env = GNUNET_MQ_msg_extra (im, hs, GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
876 GNUNET_memcpy (&im[1], pos->hello, hs);
877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
878 "Sending public HELLO with size %u for peer `%s'\n",
879 hs,
880 GNUNET_i2s (key));
881 }
882 else if ((NULL != pos->friend_only_hello) && (GNUNET_YES == tc->friend_only))
883 {
884 /* Copy friend only HELLO */
885 hs = GNUNET_HELLO_size (pos->friend_only_hello);
886 GNUNET_assert (hs < GNUNET_MAX_MESSAGE_SIZE - sizeof(struct InfoMessage));
887 env = GNUNET_MQ_msg_extra (im, hs, GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
888 GNUNET_memcpy (&im[1], pos->friend_only_hello, hs);
889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
890 "Sending friend-only HELLO with size %u for peer `%s'\n",
891 hs,
892 GNUNET_i2s (key));
893 }
894 else
895 {
896 env = GNUNET_MQ_msg (im, GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
897 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
898 "Adding no HELLO for peer `%s'\n",
899 GNUNET_i2s (key));
900 }
901 im->peer = pos->identity;
902 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (tc->client), env);
903 return GNUNET_YES;
904}
905
906
907/**
908 * @brief delete expired HELLO entries in directory
909 *
910 * @param cls pointer to current time (`struct GNUNET_TIME_Absolute *`)
911 * @param fn filename to test to see if the HELLO expired
912 * @return #GNUNET_OK (continue iteration)
913 */
914static int
915discard_hosts_helper (void *cls, const char *fn)
916{
917 struct GNUNET_TIME_Absolute *now = cls;
918 char buffer[GNUNET_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
919 const struct GNUNET_HELLO_Message *hello;
920 struct GNUNET_HELLO_Message *new_hello;
921 int read_size;
922 unsigned int cur_hello_size;
923 unsigned int new_hello_size;
924 int read_pos;
925 int write_pos;
926 unsigned int cnt;
927 char *writebuffer;
928 uint64_t fsize;
929
930 if (GNUNET_OK != GNUNET_DISK_file_size (fn, &fsize, GNUNET_YES, GNUNET_YES))
931 {
932 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING
933 | GNUNET_ERROR_TYPE_BULK,
934 "fstat",
935 fn);
936 return GNUNET_OK;
937 }
938 read_size = GNUNET_DISK_fn_read (fn, buffer, sizeof(buffer));
939
940 if ((read_size < (int) sizeof(struct GNUNET_MessageHeader)) ||
941 (fsize > GNUNET_MAX_MESSAGE_SIZE))
942 {
943 if (0 != unlink (fn))
944 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING
945 | GNUNET_ERROR_TYPE_BULK,
946 "unlink",
947 fn);
948 return GNUNET_OK;
949 }
950
951 writebuffer = GNUNET_malloc (read_size);
952 read_pos = 0;
953 write_pos = 0;
954 while (read_pos < read_size)
955 {
956 /* Check each HELLO */
957 hello = (const struct GNUNET_HELLO_Message *) &buffer[read_pos];
958 cur_hello_size = GNUNET_HELLO_size (hello);
959 if (0 == cur_hello_size)
960 {
961 /* Invalid data, discard */
962 if (0 != unlink (fn))
963 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING
964 | GNUNET_ERROR_TYPE_BULK,
965 "unlink",
966 fn);
967 GNUNET_free (writebuffer);
968 return GNUNET_OK;
969 }
970 new_hello =
971 GNUNET_HELLO_iterate_addresses (hello, GNUNET_YES, &discard_expired, now);
972 cnt = 0;
973 if (NULL != new_hello)
974 (void) GNUNET_HELLO_iterate_addresses (hello,
975 GNUNET_NO,
976 &count_addresses,
977 &cnt);
978 if ((NULL != new_hello) && (0 < cnt))
979 {
980 /* Store new HELLO to write it when done */
981 new_hello_size = GNUNET_HELLO_size (new_hello);
982 GNUNET_memcpy (&writebuffer[write_pos], new_hello, new_hello_size);
983 write_pos += new_hello_size;
984 }
985 read_pos += cur_hello_size;
986 GNUNET_free (new_hello);
987 }
988
989 if (0 < write_pos)
990 {
991 (void) GNUNET_DISK_directory_remove (fn);
992 GNUNET_assert (GNUNET_OK ==
993 GNUNET_DISK_fn_write (fn,
994 writebuffer,
995 write_pos,
996 GNUNET_DISK_PERM_USER_READ
997 | GNUNET_DISK_PERM_USER_WRITE
998 | GNUNET_DISK_PERM_GROUP_READ
999 | GNUNET_DISK_PERM_OTHER_READ));
1000 }
1001 else if (0 != unlink (fn))
1002 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING
1003 | GNUNET_ERROR_TYPE_BULK,
1004 "unlink",
1005 fn);
1006
1007 GNUNET_free (writebuffer);
1008 return GNUNET_OK;
1009}
1010
1011
1012/**
1013 * Call this method periodically to scan peerinfo/ for ancient
1014 * HELLOs to expire.
1015 *
1016 * @param cls unused
1017 */
1018static void
1019cron_clean_data_hosts (void *cls)
1020{
1021 struct GNUNET_TIME_Absolute now;
1022
1023 (void) cls;
1024 cron_clean = NULL;
1025 now = GNUNET_TIME_absolute_get ();
1026 GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
1027 _ ("Cleaning up directory `%s'\n"),
1028 networkIdDirectory);
1029 GNUNET_DISK_directory_scan (networkIdDirectory, &discard_hosts_helper, &now);
1030 cron_clean = GNUNET_SCHEDULER_add_delayed (DATA_HOST_CLEAN_FREQ,
1031 &cron_clean_data_hosts,
1032 NULL);
1033}
1034
1035
1036/**
1037 * Check HELLO-message.
1038 *
1039 * @param cls identification of the client
1040 * @param hello the actual message
1041 * @return #GNUNET_OK if @a hello is well-formed
1042 */
1043static int
1044check_hello (void *cls, const struct GNUNET_HELLO_Message *hello)
1045{
1046 struct GNUNET_PeerIdentity pid;
1047
1048 (void) cls;
1049 if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
1050 {
1051 GNUNET_break (0);
1052 return GNUNET_SYSERR;
1053 }
1054 return GNUNET_OK;
1055}
1056
1057
1058/**
1059 * Handle HELLO-message.
1060 *
1061 * @param cls identification of the client
1062 * @param hello the actual message
1063 */
1064static void
1065handle_hello (void *cls, const struct GNUNET_HELLO_Message *hello)
1066{
1067 struct GNUNET_SERVICE_Client *client = cls;
1068 struct GNUNET_PeerIdentity pid;
1069
1070 GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (hello, &pid));
1071 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1072 "HELLO message received for peer `%s'\n",
1073 GNUNET_i2s (&pid));
1074 add_host_to_known_hosts (&pid);
1075 update_hello (&pid, hello);
1076 GNUNET_SERVICE_client_continue (client);
1077}
1078
1079
1080/**
1081 * Handle GET-message.
1082 *
1083 * @param cls identification of the client
1084 * @param lpm the actual message
1085 */
1086static void
1087handle_get (void *cls, const struct ListPeerMessage *lpm)
1088{
1089 struct GNUNET_SERVICE_Client *client = cls;
1090 struct TransmitContext tcx;
1091 struct GNUNET_MessageHeader *msg;
1092 struct GNUNET_MQ_Envelope *env;
1093
1094 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1095 "GET message received for peer `%s'\n",
1096 GNUNET_i2s (&lpm->peer));
1097 tcx.friend_only = ntohl (lpm->include_friend_only);
1098 tcx.client = client;
1099 GNUNET_CONTAINER_multipeermap_get_multiple (hostmap,
1100 &lpm->peer,
1101 &add_to_tc,
1102 &tcx);
1103 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
1104 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
1105 GNUNET_SERVICE_client_continue (client);
1106}
1107
1108
1109/**
1110 * Handle GET-ALL-message.
1111 *
1112 * @param cls identification of the client
1113 * @param lapm the actual message
1114 */
1115static void
1116handle_get_all (void *cls, const struct ListAllPeersMessage *lapm)
1117{
1118 struct GNUNET_SERVICE_Client *client = cls;
1119 struct TransmitContext tcx;
1120 struct GNUNET_MQ_Envelope *env;
1121 struct GNUNET_MessageHeader *msg;
1122
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GET_ALL message received\n");
1124 tcx.friend_only = ntohl (lapm->include_friend_only);
1125 tcx.client = client;
1126 GNUNET_CONTAINER_multipeermap_iterate (hostmap, &add_to_tc, &tcx);
1127 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
1128 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
1129 GNUNET_SERVICE_client_continue (client);
1130}
1131
1132
1133/**
1134 * Handle NOTIFY-message.
1135 *
1136 * @param cls identification of the client
1137 * @param nm the actual message
1138 */
1139static void
1140handle_notify (void *cls, const struct NotifyMessage *nm)
1141{
1142 struct GNUNET_SERVICE_Client *client = cls;
1143 struct GNUNET_MQ_Handle *mq;
1144 struct TransmitContext tcx;
1145 struct GNUNET_MQ_Envelope *env;
1146 struct GNUNET_MessageHeader *msg;
1147
1148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "NOTIFY message received\n");
1149 mq = GNUNET_SERVICE_client_get_mq (client);
1150 GNUNET_SERVICE_client_mark_monitor (client);
1151 if (ntohl (nm->include_friend_only))
1152 GNUNET_notification_context_add (notify_friend_only_list, mq);
1153 else
1154 GNUNET_notification_context_add (notify_list, mq);
1155 tcx.friend_only = ntohl (nm->include_friend_only);
1156 tcx.client = client;
1157 GNUNET_CONTAINER_multipeermap_iterate (hostmap, &add_to_tc, &tcx);
1158 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
1159 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
1160 GNUNET_SERVICE_client_continue (client);
1161}
1162
1163
1164/**
1165 * Client connect callback
1166 *
1167 * @param cls unused
1168 * @param client server client
1169 * @param mq for @a client
1170 * @return @a client
1171 */
1172static void *
1173client_connect_cb (void *cls,
1174 struct GNUNET_SERVICE_Client *client,
1175 struct GNUNET_MQ_Handle *mq)
1176{
1177 (void) cls;
1178 (void) mq;
1179 return client;
1180}
1181
1182
1183/**
1184 * Client disconnect callback
1185 *
1186 * @param cls unused
1187 * @param client server client
1188 * @param app_ctx should be @a client
1189 */
1190static void
1191client_disconnect_cb (void *cls,
1192 struct GNUNET_SERVICE_Client *client,
1193 void *app_ctx)
1194{
1195 (void) cls;
1196 GNUNET_assert (app_ctx == client);
1197}
1198
1199
1200/**
1201 * Release memory taken by a host entry.
1202 *
1203 * @param cls NULL
1204 * @param key key of the host entry
1205 * @param value the `struct HostEntry` to free
1206 * @return #GNUNET_YES (continue to iterate)
1207 */
1208static int
1209free_host_entry (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
1210{
1211 struct HostEntry *he = value;
1212
1213 (void) cls;
1214 (void) key;
1215 GNUNET_free (he->hello);
1216 GNUNET_free (he->friend_only_hello);
1217 GNUNET_free (he);
1218 return GNUNET_YES;
1219}
1220
1221
1222/**
1223 * Clean up our state. Called during shutdown.
1224 *
1225 * @param cls unused
1226 */
1227static void
1228shutdown_task (void *cls)
1229{
1230 (void) cls;
1231 GNUNET_notification_context_destroy (notify_list);
1232 notify_list = NULL;
1233 GNUNET_notification_context_destroy (notify_friend_only_list);
1234 notify_friend_only_list = NULL;
1235
1236 GNUNET_CONTAINER_multipeermap_iterate (hostmap, &free_host_entry, NULL);
1237 GNUNET_CONTAINER_multipeermap_destroy (hostmap);
1238 if (NULL != stats)
1239 {
1240 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
1241 stats = NULL;
1242 }
1243 if (NULL != cron_clean)
1244 {
1245 GNUNET_SCHEDULER_cancel (cron_clean);
1246 cron_clean = NULL;
1247 }
1248 if (NULL != cron_scan)
1249 {
1250 GNUNET_SCHEDULER_cancel (cron_scan);
1251 cron_scan = NULL;
1252 }
1253 if (NULL != networkIdDirectory)
1254 {
1255 GNUNET_free (networkIdDirectory);
1256 networkIdDirectory = NULL;
1257 }
1258}
1259
1260
1261/**
1262 * Start up peerinfo service.
1263 *
1264 * @param cls closure
1265 * @param cfg configuration to use
1266 * @param service the initialized service
1267 */
1268static void
1269run (void *cls,
1270 const struct GNUNET_CONFIGURATION_Handle *cfg,
1271 struct GNUNET_SERVICE_Handle *service)
1272{
1273 char *peerdir;
1274 char *ip;
1275 struct DirScanContext dsc;
1276 int noio;
1277 int use_included;
1278
1279 (void) cls;
1280 (void) service;
1281 hostmap = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
1282 stats = GNUNET_STATISTICS_create ("peerinfo", cfg);
1283 notify_list = GNUNET_notification_context_create (0);
1284 notify_friend_only_list = GNUNET_notification_context_create (0);
1285 noio = GNUNET_CONFIGURATION_get_value_yesno (cfg, "peerinfo", "NO_IO");
1286 use_included = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1287 "peerinfo",
1288 "USE_INCLUDED_HELLOS");
1289 if (GNUNET_SYSERR == use_included)
1290 use_included = GNUNET_NO;
1291 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1292 if (GNUNET_YES != noio)
1293 {
1294 GNUNET_assert (
1295 GNUNET_OK ==
1296 GNUNET_CONFIGURATION_get_value_filename (cfg,
1297 "peerinfo",
1298 "HOSTS",
1299 &networkIdDirectory));
1300 if (GNUNET_OK != GNUNET_DISK_directory_create (networkIdDirectory))
1301 {
1302 GNUNET_SCHEDULER_shutdown ();
1303 return;
1304 }
1305
1306 cron_scan =
1307 GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
1308 &cron_scan_directory_data_hosts,
1309 NULL);
1310
1311 cron_clean =
1312 GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
1313 &cron_clean_data_hosts,
1314 NULL);
1315 if (GNUNET_YES == use_included)
1316 {
1317 ip = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
1318 GNUNET_asprintf (&peerdir, "%shellos", ip);
1319 GNUNET_free (ip);
1320
1321 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1322 _ ("Importing HELLOs from `%s'\n"),
1323 peerdir);
1324 dsc.matched = 0;
1325 dsc.remove_files = GNUNET_NO;
1326
1327 GNUNET_DISK_directory_scan (peerdir,
1328 &hosts_directory_scan_callback,
1329 &dsc);
1330 GNUNET_free (peerdir);
1331 }
1332 else
1333 {
1334 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1335 _ ("Skipping import of included HELLOs\n"));
1336 }
1337 }
1338}
1339
1340
1341/**
1342 * Define "main" method using service macro.
1343 */
1344GNUNET_SERVICE_MAIN (
1345 "peerinfo",
1346 GNUNET_SERVICE_OPTION_NONE,
1347 &run,
1348 &client_connect_cb,
1349 &client_disconnect_cb,
1350 NULL,
1351 GNUNET_MQ_hd_var_size (hello,
1352 GNUNET_MESSAGE_TYPE_HELLO,
1353 struct GNUNET_HELLO_Message,
1354 NULL),
1355 GNUNET_MQ_hd_fixed_size (get,
1356 GNUNET_MESSAGE_TYPE_PEERINFO_GET,
1357 struct ListPeerMessage,
1358 NULL),
1359 GNUNET_MQ_hd_fixed_size (get_all,
1360 GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL,
1361 struct ListAllPeersMessage,
1362 NULL),
1363 GNUNET_MQ_hd_fixed_size (notify,
1364 GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY,
1365 struct NotifyMessage,
1366 NULL),
1367 GNUNET_MQ_handler_end ());
1368
1369
1370/* end of gnunet-service-peerinfo.c */
diff --git a/src/peerinfo/peerinfo.conf.in b/src/peerinfo/peerinfo.conf.in
deleted file mode 100644
index 14a41655b..000000000
--- a/src/peerinfo/peerinfo.conf.in
+++ /dev/null
@@ -1,31 +0,0 @@
1[peerinfo]
2START_ON_DEMAND = @START_ON_DEMAND@
3@JAVAPORT@PORT = 2090
4HOSTNAME = localhost
5BINARY = gnunet-service-peerinfo
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-peerinfo.sock
9UNIX_MATCH_UID = NO
10UNIX_MATCH_GID = YES
11# DISABLE_SOCKET_FORWARDING = NO
12# USERNAME =
13# MAXBUF =
14# TIMEOUT =
15# DISABLEV6 =
16# BINDTO =
17# REJECT_FROM =
18# REJECT_FROM6 =
19# PREFIX =
20HOSTS = $GNUNET_DATA_HOME/peerinfo/hosts/
21
22# Option to disable all disk IO; only useful for testbed runs
23# (large-scale experiments); disables persistence of HELLOs!
24NO_IO = NO
25
26# Load HELLOs shipped with GNUnet
27USE_INCLUDED_HELLOS = YES
28
29[uri]
30hello = gnunet-peerinfo
31friend-hello = gnunet-peerinfo
diff --git a/src/peerinfo/peerinfo.h b/src/peerinfo/peerinfo.h
deleted file mode 100644
index 7db923d4d..000000000
--- a/src/peerinfo/peerinfo.h
+++ /dev/null
@@ -1,123 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file peerinfo/peerinfo.h
23 * @brief common internal definitions for peerinfo service
24 * @author Christian Grothoff
25 */
26
27#ifndef PEERINFO_H
28#define PEERINFO_H
29
30#include "gnunet_crypto_lib.h"
31#include "gnunet_time_lib.h"
32#include "gnunet_peerinfo_service.h"
33
34
35GNUNET_NETWORK_STRUCT_BEGIN
36
37/**
38 * Message requesting a listing of peers,
39 * restricted to the specified peer identity.
40 */
41struct ListPeerMessage
42{
43 /**
44 * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_GET
45 */
46 struct GNUNET_MessageHeader header;
47
48 /**
49 * Include friend only HELLOs and peers in callbacks
50 */
51 uint32_t include_friend_only GNUNET_PACKED;
52
53 /**
54 * Restrict to peers with this identity (optional
55 * field, check header.size!).
56 */
57 struct GNUNET_PeerIdentity peer;
58};
59
60/**
61 * Message requesting a listing of all peers,
62 * restricted to the specified peer identity.
63 */
64struct ListAllPeersMessage
65{
66 /**
67 * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL
68 */
69 struct GNUNET_MessageHeader header;
70
71 /**
72 * Include friend only HELLOs and peers in callbacks
73 */
74 uint32_t include_friend_only GNUNET_PACKED;
75};
76
77
78/**
79 * Header for all communications.
80 */
81struct NotifyMessage
82{
83 /**
84 * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY
85 */
86 struct GNUNET_MessageHeader header;
87
88 /**
89 * Include friend only HELLOs and peers in callbacks
90 */
91 uint32_t include_friend_only GNUNET_PACKED;
92};
93
94
95/**
96 * Message used to inform the client about
97 * a particular peer; this message is optionally followed
98 * by a HELLO message for the respective peer (if available).
99 * Check the header.size field to see if a HELLO is
100 * present.
101 */
102struct InfoMessage
103{
104 /**
105 * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_INFO
106 */
107 struct GNUNET_MessageHeader header;
108
109 /**
110 * Always zero.
111 */
112 uint32_t reserved GNUNET_PACKED;
113
114 /**
115 * About which peer are we talking here?
116 */
117 struct GNUNET_PeerIdentity peer;
118};
119GNUNET_NETWORK_STRUCT_END
120
121/*#ifndef PEERINFO_H*/
122#endif
123/* end of peerinfo.h */
diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c
deleted file mode 100644
index b73d9d927..000000000
--- a/src/peerinfo/peerinfo_api.c
+++ /dev/null
@@ -1,580 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
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_util_lib.h"
28#include "gnunet_protocols.h"
29#include "peerinfo.h"
30
31#define LOG(kind, ...) GNUNET_log_from (kind, "peerinfo-api", __VA_ARGS__)
32
33
34/**
35 * Context for an iteration request.
36 */
37struct GNUNET_PEERINFO_IteratorContext
38{
39 /**
40 * Kept in a DLL.
41 */
42 struct GNUNET_PEERINFO_IteratorContext *next;
43
44 /**
45 * Kept in a DLL.
46 */
47 struct GNUNET_PEERINFO_IteratorContext *prev;
48
49 /**
50 * Handle to the PEERINFO service.
51 */
52 struct GNUNET_PEERINFO_Handle *h;
53
54 /**
55 * Function to call with the results.
56 */
57 GNUNET_PEERINFO_Processor callback;
58
59 /**
60 * Closure for @e callback.
61 */
62 void *callback_cls;
63
64 /**
65 * Peer we are interested in (only valid if iteration was restricted to one peer).
66 */
67 struct GNUNET_PeerIdentity peer;
68
69 /**
70 * Is @e peer set?
71 */
72 int have_peer;
73
74 /**
75 * Only include friends in reply?
76 */
77 int include_friend_only;
78};
79
80
81/**
82 * Handle to the peerinfo service.
83 */
84struct GNUNET_PEERINFO_Handle
85{
86 /**
87 * Our configuration.
88 */
89 const struct GNUNET_CONFIGURATION_Handle *cfg;
90
91 /**
92 * Connection to the service.
93 */
94 struct GNUNET_MQ_Handle *mq;
95
96 /**
97 * Head of iterator DLL.
98 */
99 struct GNUNET_PEERINFO_IteratorContext *ic_head;
100
101 /**
102 * Tail of iterator DLL.
103 */
104 struct GNUNET_PEERINFO_IteratorContext *ic_tail;
105
106 /**
107 * ID for a reconnect task.
108 */
109 struct GNUNET_SCHEDULER_Task *r_task;
110};
111
112
113/**
114 * Close the existing connection to PEERINFO and reconnect.
115 *
116 * @param h handle to the service
117 */
118static void
119reconnect (struct GNUNET_PEERINFO_Handle *h);
120
121
122/**
123 * Connect to the peerinfo service.
124 *
125 * @param cfg configuration to use
126 * @return NULL on error (configuration related, actual connection
127 * establishment may happen asynchronously).
128 */
129struct GNUNET_PEERINFO_Handle *
130GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
131{
132 struct GNUNET_PEERINFO_Handle *h;
133
134 h = GNUNET_new (struct GNUNET_PEERINFO_Handle);
135 h->cfg = cfg;
136 reconnect (h);
137 if (NULL == h->mq)
138 {
139 GNUNET_free (h);
140 return NULL;
141 }
142 return h;
143}
144
145
146/**
147 * Disconnect from the peerinfo service. Note that all iterators must
148 * have completed or have been cancelled by the time this function is
149 * called (otherwise, calling this function is a serious error).
150 * Furthermore, if #GNUNET_PEERINFO_add_peer() operations are still
151 * pending, they will be cancelled silently on disconnect.
152 *
153 * @param h handle to disconnect
154 */
155void
156GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h)
157{
158 struct GNUNET_PEERINFO_IteratorContext *ic;
159
160 while (NULL != (ic = h->ic_head))
161 {
162 GNUNET_CONTAINER_DLL_remove (h->ic_head,
163 h->ic_tail,
164 ic);
165 GNUNET_free (ic);
166 }
167 if (NULL != h->mq)
168 {
169 GNUNET_MQ_destroy (h->mq);
170 h->mq = NULL;
171 }
172 if (NULL != h->r_task)
173 {
174 GNUNET_SCHEDULER_cancel (h->r_task);
175 h->r_task = NULL;
176 }
177 GNUNET_free (h);
178}
179
180
181/**
182 * Task scheduled to re-try connecting to the peerinfo service.
183 *
184 * @param cls the `struct GNUNET_PEERINFO_Handle *`
185 */
186static void
187reconnect_task (void *cls)
188{
189 struct GNUNET_PEERINFO_Handle *h = cls;
190
191 h->r_task = NULL;
192 reconnect (h);
193}
194
195
196/**
197 * We encountered an error, reconnect to the PEERINFO service.
198 *
199 * @param h handle to reconnect
200 */
201static void
202do_reconnect (struct GNUNET_PEERINFO_Handle *h)
203{
204 struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
205
206 GNUNET_MQ_destroy (h->mq);
207 h->mq = NULL;
208 if (NULL != ic)
209 {
210 GNUNET_CONTAINER_DLL_remove (h->ic_head,
211 h->ic_tail,
212 ic);
213 if (NULL != ic->callback)
214 ic->callback (ic->callback_cls,
215 NULL,
216 NULL,
217 _ ("Failed to receive response from `PEERINFO' service."));
218 GNUNET_free (ic);
219 }
220 h->r_task = GNUNET_SCHEDULER_add_now (&reconnect_task,
221 h);
222}
223
224
225/**
226 * We got a disconnect after asking regex to do the announcement.
227 * Retry.
228 *
229 * @param cls the `struct GNUNET_PEERINFO_Handle` to retry
230 * @param error error code
231 */
232static void
233mq_error_handler (void *cls,
234 enum GNUNET_MQ_Error error)
235{
236 struct GNUNET_PEERINFO_Handle *h = cls;
237
238 do_reconnect (h);
239}
240
241
242/**
243 * Function called when we receive an info message. Check it is
244 * well-formed.
245 *
246 * @param cls closure
247 * @param im message received
248 * @return #GNUNET_OK if the message is OK
249 */
250static int
251check_info (void *cls,
252 const struct InfoMessage *im)
253{
254 struct GNUNET_PEERINFO_Handle *h = cls;
255 struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
256 uint16_t ms = ntohs (im->header.size) - sizeof(*im);
257
258 if (0 != ntohl (im->reserved))
259 {
260 GNUNET_break (0);
261 return GNUNET_SYSERR;
262 }
263 if (NULL == ic)
264 {
265 /* didn't expect a response, bad */
266 GNUNET_break (0);
267 return GNUNET_SYSERR;
268 }
269 if ((GNUNET_YES == ic->have_peer) &&
270 (0 != GNUNET_memcmp (&ic->peer,
271 &im->peer)))
272 {
273 /* bogus message (from a different iteration call?); out of sequence! */
274 LOG (GNUNET_ERROR_TYPE_ERROR,
275 "Received HELLO for peer `%s', expected peer `%s'\n",
276 GNUNET_i2s (&im->peer),
277 GNUNET_i2s (&ic->peer));
278 GNUNET_break (0);
279 return GNUNET_SYSERR;
280 }
281 if (ms > sizeof(struct GNUNET_MessageHeader))
282 {
283 const struct GNUNET_HELLO_Message *hello;
284 struct GNUNET_PeerIdentity id;
285
286 hello = (const struct GNUNET_HELLO_Message *) &im[1];
287 if (ms != GNUNET_HELLO_size (hello))
288 {
289 /* malformed message */
290 GNUNET_break (0);
291 return GNUNET_SYSERR;
292 }
293 if (GNUNET_OK !=
294 GNUNET_HELLO_get_id (hello,
295 &id))
296 {
297 /* malformed message */
298 GNUNET_break (0);
299 return GNUNET_SYSERR;
300 }
301 if (0 != GNUNET_memcmp (&im->peer,
302 &id))
303 {
304 /* malformed message */
305 GNUNET_break (0);
306 return GNUNET_SYSERR;
307 }
308 }
309 else if (0 != ms)
310 {
311 /* malformed message */
312 GNUNET_break (0);
313 return GNUNET_SYSERR;
314 }
315 return GNUNET_OK;
316}
317
318
319/**
320 * Handle info message.
321 *
322 * @param cls closure
323 * @param im message received
324 */
325static void
326handle_info (void *cls,
327 const struct InfoMessage *im)
328{
329 struct GNUNET_PEERINFO_Handle *h = cls;
330 struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
331 const struct GNUNET_HELLO_Message *hello = NULL;
332 uint16_t ms;
333
334 ms = ntohs (im->header.size);
335 if (ms > sizeof(struct InfoMessage))
336 hello = (const struct GNUNET_HELLO_Message *) &im[1];
337 if (NULL != ic->callback)
338 ic->callback (ic->callback_cls,
339 &im->peer,
340 hello,
341 NULL);
342}
343
344
345/**
346 * Send the next IC request at the head of the queue.
347 *
348 * @param h handle
349 */
350static void
351send_ic_request (struct GNUNET_PEERINFO_Handle *h)
352{
353 struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
354 struct GNUNET_MQ_Envelope *env;
355 struct ListAllPeersMessage *lapm;
356 struct ListPeerMessage *lpm;
357
358 if (NULL == ic)
359 {
360 GNUNET_break (0);
361 return;
362 }
363 if (NULL == h->mq)
364 {
365 GNUNET_break (0);
366 return;
367 }
368 if (GNUNET_NO == ic->have_peer)
369 {
370 LOG (GNUNET_ERROR_TYPE_DEBUG,
371 "Requesting list of peers from PEERINFO service\n");
372 env = GNUNET_MQ_msg (lapm,
373 GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
374 lapm->include_friend_only = htonl (ic->include_friend_only);
375 }
376 else
377 {
378 LOG (GNUNET_ERROR_TYPE_DEBUG,
379 "Requesting information on peer `%s' from PEERINFO service\n",
380 GNUNET_i2s (&ic->peer));
381 env = GNUNET_MQ_msg (lpm,
382 GNUNET_MESSAGE_TYPE_PEERINFO_GET);
383 lpm->include_friend_only = htonl (ic->include_friend_only);
384 lpm->peer = ic->peer;
385 }
386 GNUNET_MQ_send (h->mq,
387 env);
388}
389
390
391/**
392 * Type of a function to call when we receive a message from the
393 * service. Call the iterator with the result and (if applicable)
394 * continue to receive more messages or trigger processing the next
395 * event (if applicable).
396 *
397 * @param cls closure
398 * @param msg message received, NULL on timeout or fatal error
399 */
400static void
401handle_end_iteration (void *cls,
402 const struct GNUNET_MessageHeader *msg)
403{
404 struct GNUNET_PEERINFO_Handle *h = cls;
405 struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
406
407 if (NULL == ic)
408 {
409 /* didn't expect a response, reconnect */
410 GNUNET_break (0);
411 reconnect (h);
412 return;
413 }
414 LOG (GNUNET_ERROR_TYPE_DEBUG,
415 "Received end of list of peers from PEERINFO service\n");
416 GNUNET_CONTAINER_DLL_remove (h->ic_head,
417 h->ic_tail,
418 ic);
419 if (NULL != h->ic_head)
420 send_ic_request (h);
421 if (NULL != ic->callback)
422 ic->callback (ic->callback_cls,
423 NULL,
424 NULL,
425 NULL);
426 GNUNET_free (ic);
427}
428
429
430/**
431 * Close the existing connection to PEERINFO and reconnect.
432 *
433 * @param h handle to the service
434 */
435static void
436reconnect (struct GNUNET_PEERINFO_Handle *h)
437{
438 struct GNUNET_MQ_MessageHandler handlers[] = {
439 GNUNET_MQ_hd_var_size (info,
440 GNUNET_MESSAGE_TYPE_PEERINFO_INFO,
441 struct InfoMessage,
442 h),
443 GNUNET_MQ_hd_fixed_size (end_iteration,
444 GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END,
445 struct GNUNET_MessageHeader,
446 h),
447 GNUNET_MQ_handler_end ()
448 };
449
450 if (NULL != h->r_task)
451 {
452 GNUNET_SCHEDULER_cancel (h->r_task);
453 h->r_task = NULL;
454 }
455 if (NULL != h->mq)
456 {
457 GNUNET_MQ_destroy (h->mq);
458 h->mq = NULL;
459 }
460 h->mq = GNUNET_CLIENT_connect (h->cfg,
461 "peerinfo",
462 handlers,
463 &mq_error_handler,
464 h);
465 if (NULL != h->ic_head)
466 send_ic_request (h);
467}
468
469
470/**
471 * Call a method for each known matching host. The callback method
472 * will be invoked once for each matching host and then finally once
473 * with a NULL pointer. After that final invocation, the iterator
474 * context must no longer be used.
475 *
476 * Instead of calling this function with `peer == NULL` it is often
477 * better to use #GNUNET_PEERINFO_notify().
478 *
479 * @param h handle to the peerinfo service
480 * @param include_friend_only include HELLO messages for friends only
481 * @param peer restrict iteration to this peer only (can be NULL)
482 * @param callback the method to call for each peer
483 * @param callback_cls closure for @a callback
484 * @return iterator context
485 */
486struct GNUNET_PEERINFO_IteratorContext *
487GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
488 int include_friend_only,
489 const struct GNUNET_PeerIdentity *peer,
490 GNUNET_PEERINFO_Processor callback,
491 void *callback_cls)
492{
493 struct GNUNET_PEERINFO_IteratorContext *ic;
494
495 ic = GNUNET_new (struct GNUNET_PEERINFO_IteratorContext);
496 ic->h = h;
497 ic->include_friend_only = include_friend_only;
498 ic->callback = callback;
499 ic->callback_cls = callback_cls;
500 if (NULL != peer)
501 {
502 ic->have_peer = GNUNET_YES;
503 ic->peer = *peer;
504 }
505 GNUNET_CONTAINER_DLL_insert_tail (h->ic_head,
506 h->ic_tail,
507 ic);
508 if (h->ic_head == ic)
509 send_ic_request (h);
510 return ic;
511}
512
513
514/**
515 * Cancel an iteration over peer information.
516 *
517 * @param ic context of the iterator to cancel
518 */
519void
520GNUNET_PEERINFO_iterate_cancel (struct GNUNET_PEERINFO_IteratorContext *ic)
521{
522 struct GNUNET_PEERINFO_Handle *h = ic->h;
523
524 ic->callback = NULL;
525 if (ic == h->ic_head)
526 return;
527 GNUNET_CONTAINER_DLL_remove (h->ic_head,
528 h->ic_tail,
529 ic);
530 GNUNET_free (ic);
531}
532
533
534/**
535 * Add a host to the persistent list. This method operates in
536 * semi-reliable mode: if the transmission is not completed by
537 * the time #GNUNET_PEERINFO_disconnect() is called, it will be
538 * aborted. Furthermore, if a second HELLO is added for the
539 * same peer before the first one was transmitted, PEERINFO may
540 * merge the two HELLOs prior to transmission to the service.
541 *
542 * @param h handle to the peerinfo service
543 * @param hello the verified (!) HELLO message
544 * @param cont continuation to call when done, NULL is allowed
545 * @param cont_cls closure for @a cont
546 * @return handle to cancel add operation; all pending
547 * 'add' operations will be cancelled automatically
548 * on disconnect, so it is not necessary to keep this
549 * handle (unless @a cont is NULL and at some point
550 * calling @a cont must be prevented)
551 */
552struct GNUNET_MQ_Envelope *
553GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h,
554 const struct GNUNET_HELLO_Message *hello,
555 GNUNET_SCHEDULER_TaskCallback cont,
556 void *cont_cls)
557{
558 struct GNUNET_MQ_Envelope *env;
559 struct GNUNET_PeerIdentity peer;
560
561 if (NULL == h->mq)
562 return NULL;
563 GNUNET_assert (GNUNET_OK ==
564 GNUNET_HELLO_get_id (hello,
565 &peer));
566 LOG (GNUNET_ERROR_TYPE_DEBUG,
567 "Adding peer `%s' to PEERINFO database\n",
568 GNUNET_i2s (&peer));
569 env = GNUNET_MQ_msg_copy ((const struct GNUNET_MessageHeader *) hello);
570 if (NULL != cont)
571 GNUNET_MQ_notify_sent (env,
572 cont,
573 cont_cls);
574 GNUNET_MQ_send (h->mq,
575 env);
576 return env;
577}
578
579
580/* end of peerinfo_api.c */
diff --git a/src/peerinfo/peerinfo_api_notify.c b/src/peerinfo/peerinfo_api_notify.c
deleted file mode 100644
index 5f4c123ff..000000000
--- a/src/peerinfo/peerinfo_api_notify.c
+++ /dev/null
@@ -1,291 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file peerinfo/peerinfo_api_notify.c
23 * @brief notify API to access peerinfo service
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_peerinfo_service.h"
29#include "gnunet_protocols.h"
30#include "peerinfo.h"
31
32#define LOG(kind, ...) GNUNET_log_from (kind, "peerinfo-api", __VA_ARGS__)
33
34/**
35 * Context for the info handler.
36 */
37struct GNUNET_PEERINFO_NotifyContext
38{
39 /**
40 * Our connection to the PEERINFO service.
41 */
42 struct GNUNET_MQ_Handle *mq;
43
44 /**
45 * Function to call with information.
46 */
47 GNUNET_PEERINFO_Processor callback;
48
49 /**
50 * Closure for @e callback.
51 */
52 void *callback_cls;
53
54 /**
55 * Configuration.
56 */
57 const struct GNUNET_CONFIGURATION_Handle *cfg;
58
59 /**
60 * Tasked used for delayed re-connection attempt.
61 */
62 struct GNUNET_SCHEDULER_Task *task;
63
64 /**
65 * Include friend only HELLOs in callbacks
66 */
67 int include_friend_only;
68};
69
70
71/**
72 * Task to re-try connecting to peerinfo.
73 *
74 * @param cls the `struct GNUNET_PEERINFO_NotifyContext *`
75 */
76static void
77reconnect (void *cls);
78
79
80/**
81 * We encountered an error, reconnect to the service.
82 *
83 * @param nc context to reconnect
84 */
85static void
86do_reconnect (struct GNUNET_PEERINFO_NotifyContext *nc)
87{
88 GNUNET_MQ_destroy (nc->mq);
89 nc->mq = NULL;
90 nc->task = GNUNET_SCHEDULER_add_now (&reconnect,
91 nc);
92}
93
94
95/**
96 * We got a disconnect after asking regex to do the announcement.
97 * Retry.
98 *
99 * @param cls the `struct GNUNET_PEERINFO_NotifyContext` to retry
100 * @param error error code
101 */
102static void
103mq_error_handler (void *cls,
104 enum GNUNET_MQ_Error error)
105{
106 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
107
108 do_reconnect (nc);
109}
110
111
112/**
113 * Check that a peerinfo information message is well-formed.
114 *
115 * @param cls closure
116 * @param im message received
117 * @return #GNUNET_OK if the message is well-formed
118 */
119static int
120check_notification (void *cls,
121 const struct InfoMessage *im)
122{
123 uint16_t ms = ntohs (im->header.size) - sizeof(*im);
124
125 if (ms >= sizeof(struct GNUNET_MessageHeader))
126 {
127 const struct GNUNET_HELLO_Message *hello;
128
129 hello = (const struct GNUNET_HELLO_Message *) &im[1];
130 if (ms != GNUNET_HELLO_size (hello))
131 {
132 GNUNET_break (0);
133 return GNUNET_SYSERR;
134 }
135 return GNUNET_OK;
136 }
137 if (0 != ms)
138 {
139 GNUNET_break (0);
140 return GNUNET_SYSERR;
141 }
142 return GNUNET_OK; /* odd... */
143}
144
145
146/**
147 * Receive a peerinfo information message, process it.
148 *
149 * @param cls closure
150 * @param im message received
151 */
152static void
153handle_notification (void *cls,
154 const struct InfoMessage *im)
155{
156 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
157 const struct GNUNET_HELLO_Message *hello;
158 uint16_t ms = ntohs (im->header.size) - sizeof(struct InfoMessage);
159
160 if (0 == ms)
161 return;
162 hello = (const struct GNUNET_HELLO_Message *) &im[1];
163 LOG (GNUNET_ERROR_TYPE_DEBUG,
164 "Received information about peer `%s' from peerinfo database\n",
165 GNUNET_i2s (&im->peer));
166 nc->callback (nc->callback_cls,
167 &im->peer,
168 hello,
169 NULL);
170}
171
172
173/**
174 * Type of a function to call when we receive a message from the
175 * service. Call the iterator with the result and (if applicable)
176 * continue to receive more messages or trigger processing the next
177 * event (if applicable).
178 *
179 * @param cls closure
180 * @param msg message received, NULL on timeout or fatal error
181 */
182static void
183handle_end_iteration (void *cls,
184 const struct GNUNET_MessageHeader *msg)
185{
186 /* these are ignored by the notify API */
187}
188
189
190/**
191 * Task to re-try connecting to peerinfo.
192 *
193 * @param cls the `struct GNUNET_PEERINFO_NotifyContext *`
194 */
195static void
196reconnect (void *cls)
197{
198 struct GNUNET_PEERINFO_NotifyContext *nc = cls;
199 struct GNUNET_MQ_MessageHandler handlers[] = {
200 GNUNET_MQ_hd_var_size (notification,
201 GNUNET_MESSAGE_TYPE_PEERINFO_INFO,
202 struct InfoMessage,
203 nc),
204 GNUNET_MQ_hd_fixed_size (end_iteration,
205 GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END,
206 struct GNUNET_MessageHeader,
207 nc),
208 GNUNET_MQ_handler_end ()
209 };
210 struct GNUNET_MQ_Envelope *env;
211 struct NotifyMessage *nm;
212
213 nc->task = NULL;
214 nc->mq = GNUNET_CLIENT_connect (nc->cfg,
215 "peerinfo",
216 handlers,
217 &mq_error_handler,
218 nc);
219 if (NULL == nc->mq)
220 return;
221 env = GNUNET_MQ_msg (nm,
222 GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY);
223 nm->include_friend_only = htonl (nc->include_friend_only);
224 GNUNET_MQ_send (nc->mq,
225 env);
226}
227
228
229/**
230 * Call a method whenever our known information about peers
231 * changes. Initially calls the given function for all known
232 * peers and then only signals changes.
233 *
234 * If @a include_friend_only is set to #GNUNET_YES peerinfo will include HELLO
235 * messages which are intended for friend to friend mode and which do not
236 * have to be gossiped. Otherwise these messages are skipped.
237 *
238 * @param cfg configuration to use
239 * @param include_friend_only include HELLO messages for friends only
240 * @param callback the method to call for each peer
241 * @param callback_cls closure for @a callback
242 * @return NULL on error
243 */
244struct GNUNET_PEERINFO_NotifyContext *
245GNUNET_PEERINFO_notify (const struct GNUNET_CONFIGURATION_Handle *cfg,
246 int include_friend_only,
247 GNUNET_PEERINFO_Processor callback,
248 void *callback_cls)
249{
250 struct GNUNET_PEERINFO_NotifyContext *nc;
251
252 nc = GNUNET_new (struct GNUNET_PEERINFO_NotifyContext);
253 nc->cfg = cfg;
254 nc->callback = callback;
255 nc->callback_cls = callback_cls;
256 nc->include_friend_only = include_friend_only;
257 reconnect (nc);
258 if (NULL == nc->mq)
259 {
260 LOG (GNUNET_ERROR_TYPE_WARNING,
261 "Could not connect to PEERINFO service.\n");
262 GNUNET_free (nc);
263 return NULL;
264 }
265 return nc;
266}
267
268
269/**
270 * Stop notifying about changes.
271 *
272 * @param nc context to stop notifying
273 */
274void
275GNUNET_PEERINFO_notify_cancel (struct GNUNET_PEERINFO_NotifyContext *nc)
276{
277 if (NULL != nc->mq)
278 {
279 GNUNET_MQ_destroy (nc->mq);
280 nc->mq = NULL;
281 }
282 if (NULL != nc->task)
283 {
284 GNUNET_SCHEDULER_cancel (nc->task);
285 nc->task = NULL;
286 }
287 GNUNET_free (nc);
288}
289
290
291/* end of peerinfo_api_notify.c */
diff --git a/src/peerinfo/perf_peerinfo_api.c b/src/peerinfo/perf_peerinfo_api.c
deleted file mode 100644
index 055388d43..000000000
--- a/src/peerinfo/perf_peerinfo_api.c
+++ /dev/null
@@ -1,193 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2004, 2009, 2010, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file peerinfo/perf_peerinfo_api.c
23 * @brief testcase for peerinfo_api.c, hopefully hammer the peerinfo service,
24 * this performance test adds up to 5000 peers with one address each and checks
25 * over how many peers it can iterate before receiving a timeout after 5 seconds
26 * @author Nathan Evans
27 */
28
29#include "platform.h"
30#include "gnunet_hello_lib.h"
31#include "gnunet_util_lib.h"
32#include "gnunet_testing_lib.h"
33#include "gnunet_peerinfo_service.h"
34#include "peerinfo.h"
35#include <gauger.h>
36
37#define NUM_REQUESTS 5000
38
39static struct GNUNET_PEERINFO_IteratorContext *ic[NUM_REQUESTS];
40
41static struct GNUNET_PEERINFO_Handle *h;
42
43static unsigned int numpeers;
44
45static struct GNUNET_PeerIdentity pid;
46
47static struct GNUNET_SCHEDULER_Task *tt;
48
49
50static void
51do_shutdown (void *cls)
52{
53 if (NULL != tt)
54 {
55 GNUNET_SCHEDULER_cancel (tt);
56 tt = NULL;
57 }
58 for (unsigned int i = 0; i < NUM_REQUESTS; i++)
59 if (NULL != ic[i])
60 GNUNET_PEERINFO_iterate_cancel (ic[i]);
61 GNUNET_PEERINFO_disconnect (h);
62 h = NULL;
63}
64
65
66static void
67do_timeout (void *cls)
68{
69 tt = NULL;
70 GNUNET_SCHEDULER_shutdown ();
71}
72
73
74static int
75check_it (void *cls,
76 const struct GNUNET_HELLO_Address *address,
77 struct GNUNET_TIME_Absolute expiration)
78{
79 return GNUNET_OK;
80}
81
82
83static ssize_t
84address_generator (void *cls, size_t max, void *buf)
85{
86 size_t *agc = cls;
87 ssize_t ret;
88 char *caddress;
89 struct GNUNET_HELLO_Address address;
90
91 if (*agc == 0)
92 return GNUNET_SYSERR; /* Done */
93
94 GNUNET_asprintf (&caddress, "Address%d", *agc);
95 address.peer = pid;
96 address.address_length = strlen (caddress) + 1;
97 address.address = caddress;
98 address.transport_name = "peerinfotest";
99 ret =
100 GNUNET_HELLO_add_address (&address,
101 GNUNET_TIME_relative_to_absolute
102 (GNUNET_TIME_UNIT_HOURS), buf, max);
103 GNUNET_free (caddress);
104 *agc = 0;
105 return ret;
106}
107
108
109static void
110add_peer (size_t i)
111{
112 struct GNUNET_HELLO_Message *h2;
113
114 memset (&pid, i, sizeof(pid));
115 h2 = GNUNET_HELLO_create (&pid.public_key,
116 &address_generator,
117 &i,
118 GNUNET_NO);
119 GNUNET_PEERINFO_add_peer (h, h2, NULL, NULL);
120 GNUNET_free (h2);
121}
122
123
124static void
125process (void *cls,
126 const struct GNUNET_PeerIdentity *peer,
127 const struct GNUNET_HELLO_Message *hello,
128 const char *err_msg)
129{
130 struct GNUNET_PEERINFO_IteratorContext **icp = cls;
131
132 if (NULL == peer)
133 {
134 *icp = NULL;
135 return;
136 }
137 numpeers++;
138 if (0 && (NULL != hello))
139 GNUNET_HELLO_iterate_addresses (hello,
140 GNUNET_NO,
141 &check_it,
142 NULL);
143}
144
145
146static void
147run (void *cls,
148 const struct GNUNET_CONFIGURATION_Handle *cfg,
149 struct GNUNET_TESTING_Peer *peer)
150{
151 h = GNUNET_PEERINFO_connect (cfg);
152 GNUNET_assert (h != NULL);
153 for (unsigned int i = 0; i < NUM_REQUESTS; i++)
154 {
155 add_peer (i);
156 ic[i] = GNUNET_PEERINFO_iterate (h,
157 GNUNET_YES,
158 NULL,
159 &process,
160 &ic[i]);
161 }
162 tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (
163 GNUNET_TIME_UNIT_SECONDS,
164 5),
165 &do_timeout,
166 NULL);
167 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
168 NULL);
169}
170
171
172int
173main (int argc,
174 char *argv[])
175{
176 if (0 != GNUNET_TESTING_service_run ("perf-gnunet-peerinfo",
177 "peerinfo",
178 "test_peerinfo_api_data.conf",
179 &run, NULL))
180 return 1;
181 fprintf (stderr,
182 "Received %u/%u calls before timeout\n",
183 numpeers,
184 NUM_REQUESTS * NUM_REQUESTS / 2);
185 GAUGER ("PEERINFO",
186 "Peerinfo lookups",
187 numpeers / 5,
188 "peers/s");
189 return 0;
190}
191
192
193/* end of perf_peerinfo_api.c */
diff --git a/src/peerinfo/test_peerinfo_api.c b/src/peerinfo/test_peerinfo_api.c
deleted file mode 100644
index 27df6e37b..000000000
--- a/src/peerinfo/test_peerinfo_api.c
+++ /dev/null
@@ -1,172 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2004, 2009 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
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#include "platform.h"
30#include "gnunet_hello_lib.h"
31#include "gnunet_util_lib.h"
32#include "gnunet_peerinfo_service.h"
33#include "gnunet_testing_lib.h"
34#include "peerinfo.h"
35
36static struct GNUNET_PEERINFO_IteratorContext *ic;
37
38static struct GNUNET_PEERINFO_Handle *h;
39
40static unsigned int retries;
41
42static int global_ret;
43
44
45static int
46check_it (void *cls, const struct GNUNET_HELLO_Address *address,
47 struct GNUNET_TIME_Absolute expiration)
48{
49 unsigned int *agc = cls;
50
51 if (address != NULL)
52 {
53 GNUNET_assert (0 == strcmp ("peerinfotest", address->transport_name));
54 GNUNET_assert (0 ==
55 strncmp ("Address", address->address,
56 address->address_length));
57 (*agc) -= (1 << (address->address_length - 1));
58 }
59 return GNUNET_OK;
60}
61
62
63static ssize_t
64address_generator (void *cls, size_t max, void *buf)
65{
66 size_t *agc = cls;
67 ssize_t ret;
68 struct GNUNET_HELLO_Address address;
69
70 if (0 == *agc)
71 return GNUNET_SYSERR; /* Done */
72 memset (&address.peer, 0, sizeof(struct GNUNET_PeerIdentity));
73 address.address = "Address";
74 address.transport_name = "peerinfotest";
75 address.address_length = *agc;
76 ret =
77 GNUNET_HELLO_add_address (&address,
78 GNUNET_TIME_relative_to_absolute
79 (GNUNET_TIME_UNIT_HOURS), buf, max);
80 (*agc)--;
81 return ret;
82}
83
84
85struct GNUNET_PeerIdentity pid;
86
87static void
88add_peer ()
89{
90 struct GNUNET_HELLO_Message *h2;
91 size_t agc;
92
93 agc = 2;
94 memset (&pid, 32, sizeof(pid));
95 h2 = GNUNET_HELLO_create (&pid.public_key, &address_generator, &agc,
96 GNUNET_NO);
97 GNUNET_PEERINFO_add_peer (h, h2, NULL, NULL);
98 GNUNET_free (h2);
99}
100
101
102static void
103process (void *cls, const struct GNUNET_PeerIdentity *peer,
104 const struct GNUNET_HELLO_Message *hello, const char *err_msg)
105{
106 unsigned int agc;
107
108 if (err_msg != NULL)
109 {
110 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
111 _ ("Error in communication with PEERINFO service\n"));
112 }
113
114 if (peer == NULL)
115 {
116 ic = NULL;
117 if ((3 == global_ret) && (retries < 50))
118 {
119 /* try again */
120 retries++;
121 add_peer ();
122 ic = GNUNET_PEERINFO_iterate (h, GNUNET_NO, NULL,
123 &process,
124 cls);
125 return;
126 }
127 GNUNET_assert (peer == NULL);
128 GNUNET_assert (2 == global_ret);
129 GNUNET_PEERINFO_disconnect (h);
130 h = NULL;
131 global_ret = 0;
132 return;
133 }
134 if (hello != NULL)
135 {
136 GNUNET_assert (3 == global_ret);
137 agc = 3;
138 GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO,
139 &check_it, &agc);
140 GNUNET_assert (agc == 0);
141 global_ret = 2;
142 }
143}
144
145
146static void
147run (void *cls,
148 const struct GNUNET_CONFIGURATION_Handle *cfg,
149 struct GNUNET_TESTING_Peer *peer)
150{
151 h = GNUNET_PEERINFO_connect (cfg);
152 GNUNET_assert (NULL != h);
153 add_peer ();
154 ic = GNUNET_PEERINFO_iterate (h, GNUNET_NO, &pid,
155 &process, cls);
156}
157
158
159int
160main (int argc, char *argv[])
161{
162 global_ret = 3;
163 if (0 != GNUNET_TESTING_service_run ("test-gnunet-peerinfo",
164 "peerinfo",
165 "test_peerinfo_api_data.conf",
166 &run, NULL))
167 return 1;
168 return global_ret;
169}
170
171
172/* end of test_peerinfo_api.c */
diff --git a/src/peerinfo/test_peerinfo_api_data.conf b/src/peerinfo/test_peerinfo_api_data.conf
deleted file mode 100644
index e632c341f..000000000
--- a/src/peerinfo/test_peerinfo_api_data.conf
+++ /dev/null
@@ -1,15 +0,0 @@
1[PATHS]
2GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-peerinfo/
3
4[peerinfo]
5PORT = 22354
6
7[dns]
8START_ON_DEMAND = NO
9
10
11
12[nse]
13START_ON_DEMAND = NO
14
15
diff --git a/src/peerinfo/test_peerinfo_api_friend_only.c b/src/peerinfo/test_peerinfo_api_friend_only.c
deleted file mode 100644
index a5414e701..000000000
--- a/src/peerinfo/test_peerinfo_api_friend_only.c
+++ /dev/null
@@ -1,172 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2004, 2009 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file peerinfo/test_peerinfo_api_friend_only.c
23 * @brief testcase friend only HELLO restrictions in for peerinfo
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 *
27 * TODO:
28 * - test merging of HELLOs (add same peer twice...)
29 */
30#include "platform.h"
31#include "gnunet_hello_lib.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_peerinfo_service.h"
34#include "gnunet_testing_lib.h"
35
36
37static struct GNUNET_PEERINFO_IteratorContext *ic;
38
39static struct GNUNET_PEERINFO_Handle *h;
40
41static struct GNUNET_PeerIdentity pid;
42
43static unsigned int retries;
44
45static int global_ret;
46
47
48static ssize_t
49address_generator (void *cls,
50 size_t max,
51 void *buf)
52{
53 size_t *agc = cls;
54 ssize_t ret;
55 struct GNUNET_HELLO_Address address;
56
57 if (0 == *agc)
58 return GNUNET_SYSERR; /* Done */
59 memset (&address.peer,
60 0,
61 sizeof(struct GNUNET_PeerIdentity));
62 address.address = "Address";
63 address.transport_name = "peerinfotest";
64 address.address_length = *agc;
65 ret = GNUNET_HELLO_add_address (&address,
66 GNUNET_TIME_relative_to_absolute (
67 GNUNET_TIME_UNIT_HOURS),
68 buf,
69 max);
70 (*agc)--;
71 return ret;
72}
73
74
75static void
76add_peer ()
77{
78 struct GNUNET_HELLO_Message *h2;
79 size_t agc;
80
81 agc = 2;
82 memset (&pid, 32, sizeof(pid));
83 h2 = GNUNET_HELLO_create (&pid.public_key,
84 &address_generator,
85 &agc,
86 GNUNET_YES);
87 GNUNET_PEERINFO_add_peer (h,
88 h2,
89 NULL,
90 NULL);
91 GNUNET_free (h2);
92}
93
94
95static void
96process (void *cls,
97 const struct GNUNET_PeerIdentity *peer,
98 const struct GNUNET_HELLO_Message *hello,
99 const char *err_msg)
100{
101 if (NULL != err_msg)
102 {
103 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
104 "Error in communication with PEERINFO service: %s\n",
105 err_msg);
106 }
107 if (NULL == peer)
108 {
109 ic = NULL;
110 if ((3 == global_ret) && (retries < 50))
111 {
112 /* try again */
113 retries++;
114 add_peer ();
115 ic = GNUNET_PEERINFO_iterate (h,
116 GNUNET_NO,
117 NULL,
118 &process,
119 cls);
120 return;
121 }
122 GNUNET_assert (peer == NULL);
123 GNUNET_PEERINFO_disconnect (h);
124 h = NULL;
125 global_ret = 0;
126 return;
127 }
128
129 if ((NULL != hello) &&
130 (GNUNET_YES == GNUNET_HELLO_is_friend_only (hello)))
131 {
132 fprintf (stderr,
133 "Received friend-only HELLO\n");
134 global_ret = 1;
135 GNUNET_PEERINFO_disconnect (h);
136 h = NULL;
137 return;
138 }
139}
140
141
142static void
143run (void *cls,
144 const struct GNUNET_CONFIGURATION_Handle *cfg,
145 struct GNUNET_TESTING_Peer *peer)
146{
147 h = GNUNET_PEERINFO_connect (cfg);
148 GNUNET_assert (NULL != h);
149 add_peer ();
150 ic = GNUNET_PEERINFO_iterate (h,
151 GNUNET_NO,
152 &pid,
153 &process,
154 NULL);
155}
156
157
158int
159main (int argc,
160 char *argv[])
161{
162 global_ret = 3;
163 if (0 != GNUNET_TESTING_service_run ("test-peerinfo-api-friend-only",
164 "peerinfo",
165 "test_peerinfo_api_data.conf",
166 &run, NULL))
167 return 1;
168 return global_ret;
169}
170
171
172/* end of test_peerinfo_api_friend_only */
diff --git a/src/peerinfo/test_peerinfo_api_notify_friend_only.c b/src/peerinfo/test_peerinfo_api_notify_friend_only.c
deleted file mode 100644
index 6d5793dcf..000000000
--- a/src/peerinfo/test_peerinfo_api_notify_friend_only.c
+++ /dev/null
@@ -1,261 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2004, 2009 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file peerinfo/test_peerinfo_api_notify_friend_only.c
23 * @brief testcase friend only HELLO restrictions in for peerinfo
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 *
27 * TODO:
28 * - test merging of HELLOs (add same peer twice...)
29 */
30#include "platform.h"
31#include "gnunet_hello_lib.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_peerinfo_service.h"
34#include "gnunet_testing_lib.h"
35#include "peerinfo.h"
36
37#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
38
39static struct GNUNET_PEERINFO_Handle *h;
40static struct GNUNET_PEERINFO_NotifyContext *pnc_w_fo;
41static struct GNUNET_PEERINFO_NotifyContext *pnc_wo_fo;
42
43static const struct GNUNET_CONFIGURATION_Handle *mycfg;
44
45static int global_ret;
46
47/**
48 * Did we get a HELLO callback for notification handle with friend HELLOS
49 * (expected)
50 */
51static int res_cb_w_fo;
52
53/**
54 * Did we get a HELLO callback for notification handle without friend HELLOS
55 * (not expected)
56 */
57static int res_cb_wo_fo;
58
59struct GNUNET_PeerIdentity pid;
60
61struct GNUNET_SCHEDULER_Task *timeout_task;
62
63static void
64end_badly (void *cls)
65{
66 timeout_task = NULL;
67 GNUNET_break (0);
68 if (NULL != pnc_wo_fo)
69 {
70 GNUNET_PEERINFO_notify_cancel (pnc_wo_fo);
71 pnc_wo_fo = NULL;
72 }
73 if (NULL != pnc_w_fo)
74 {
75 GNUNET_PEERINFO_notify_cancel (pnc_w_fo);
76 pnc_w_fo = NULL;
77 }
78 if (NULL != h)
79 {
80 GNUNET_PEERINFO_disconnect (h);
81 h = NULL;
82 }
83 global_ret = 255;
84}
85
86
87static void
88done (void *cls)
89{
90 if (NULL != pnc_w_fo)
91 GNUNET_PEERINFO_notify_cancel (pnc_w_fo);
92 pnc_w_fo = NULL;
93 if (NULL != pnc_wo_fo)
94 GNUNET_PEERINFO_notify_cancel (pnc_wo_fo);
95 pnc_wo_fo = NULL;
96 GNUNET_PEERINFO_disconnect (h);
97 h = NULL;
98
99 if (NULL != timeout_task)
100 {
101 GNUNET_SCHEDULER_cancel (timeout_task);
102 timeout_task = NULL;
103 }
104
105 if ((GNUNET_YES == res_cb_w_fo) && (GNUNET_NO == res_cb_wo_fo))
106 global_ret = 0;
107 else
108 GNUNET_break (0);
109}
110
111
112static ssize_t
113address_generator (void *cls, size_t max, void *buf)
114{
115 size_t *agc = cls;
116 ssize_t ret;
117 struct GNUNET_HELLO_Address address;
118
119 if (0 == *agc)
120 return GNUNET_SYSERR; /* Done */
121 memset (&address.peer, 0, sizeof(struct GNUNET_PeerIdentity));
122 address.address = "Address";
123 address.transport_name = "peerinfotest";
124 address.address_length = *agc;
125 ret = GNUNET_HELLO_add_address (&address,
126 GNUNET_TIME_relative_to_absolute (
127 GNUNET_TIME_UNIT_HOURS), buf, max);
128 (*agc)--;
129 return ret;
130}
131
132
133static void
134process_w_fo (void *cls,
135 const struct GNUNET_PeerIdentity *peer,
136 const struct GNUNET_HELLO_Message *hello,
137 const char *err_msg)
138{
139 if (err_msg != NULL)
140 {
141 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
142 _ ("Error in communication with PEERINFO service\n"));
143 GNUNET_SCHEDULER_add_now (&done, NULL);
144 return;
145 }
146
147 if (NULL != peer)
148 {
149 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
150 "Received callback for peer `%s' %s HELLO\n", GNUNET_i2s (peer),
151 (NULL != hello) ? "with" : "without");
152
153 if (NULL == hello)
154 return;
155
156 if (GNUNET_NO == GNUNET_HELLO_is_friend_only (hello))
157 {
158 GNUNET_break (0);
159 return;
160 }
161
162 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received %s HELLO for peer `%s'\n",
163 (GNUNET_YES == GNUNET_HELLO_is_friend_only (hello)) ?
164 "friend only" : "public",
165 GNUNET_i2s (peer));
166 if (0 == GNUNET_memcmp (&pid, peer))
167 {
168 res_cb_w_fo = GNUNET_YES;
169 GNUNET_SCHEDULER_add_now (&done, NULL);
170 }
171 return;
172 }
173}
174
175
176static void
177process_wo_fo (void *cls, const struct GNUNET_PeerIdentity *peer,
178 const struct GNUNET_HELLO_Message *hello, const char *err_msg)
179{
180 if (err_msg != NULL)
181 {
182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
183 _ ("Error in communication with PEERINFO service\n"));
184 GNUNET_SCHEDULER_add_now (&done, NULL);
185 return;
186 }
187
188 if (NULL != peer)
189 {
190 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
191 "Received callback for peer `%s' %s HELLO\n", GNUNET_i2s (peer),
192 (NULL != hello) ? "with" : "without");
193
194 if (NULL == hello)
195 return;
196
197 if (GNUNET_YES == GNUNET_HELLO_is_friend_only (hello))
198 {
199 GNUNET_break (0);
200 return;
201 }
202
203 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received %s HELLO for peer `%s'\n",
204 (GNUNET_YES == GNUNET_HELLO_is_friend_only (hello)) ?
205 "friend only" : "public",
206 GNUNET_i2s (peer));
207 if (0 == GNUNET_memcmp (&pid, peer))
208 {
209 GNUNET_break (0);
210 res_cb_wo_fo = GNUNET_YES;
211 }
212 }
213}
214
215
216static void
217add_peer ()
218{
219 struct GNUNET_HELLO_Message *h2;
220 size_t agc;
221
222 agc = 2;
223 memset (&pid, 32, sizeof(pid));
224 h2 = GNUNET_HELLO_create (&pid.public_key, &address_generator, &agc,
225 GNUNET_YES);
226 GNUNET_PEERINFO_add_peer (h, h2, NULL, NULL);
227 GNUNET_free (h2);
228}
229
230
231static void
232run (void *cls,
233 const struct GNUNET_CONFIGURATION_Handle *cfg,
234 struct GNUNET_TESTING_Peer *peer)
235{
236 timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
237 mycfg = cfg;
238 pnc_w_fo = GNUNET_PEERINFO_notify (mycfg, GNUNET_YES, &process_w_fo, NULL);
239 pnc_wo_fo = GNUNET_PEERINFO_notify (mycfg, GNUNET_NO, &process_wo_fo, NULL);
240 h = GNUNET_PEERINFO_connect (cfg);
241 GNUNET_assert (NULL != h);
242 add_peer ();
243}
244
245
246int
247main (int argc, char *argv[])
248{
249 res_cb_w_fo = GNUNET_NO;
250 res_cb_wo_fo = GNUNET_NO;
251 global_ret = 3;
252 if (0 != GNUNET_TESTING_service_run ("test-peerinfo-api-friend-only",
253 "peerinfo",
254 "test_peerinfo_api_data.conf",
255 &run, NULL))
256 return 1;
257 return global_ret;
258}
259
260
261/* end of test_peerinfo_api_notify_friend_only.c */
diff --git a/src/peerinfo/test_peerinfo_shipped_hellos.c b/src/peerinfo/test_peerinfo_shipped_hellos.c
deleted file mode 100644
index 45ea73be6..000000000
--- a/src/peerinfo/test_peerinfo_shipped_hellos.c
+++ /dev/null
@@ -1,144 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2004, 2009 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file peerinfo/test_peerinfo_shipped_hellos.c
23 * @brief testcase for shipped HELLOs getting parsed
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 *
27 */
28#include "platform.h"
29#include "gnunet_hello_lib.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_peerinfo_service.h"
32#include "gnunet_testing_lib.h"
33#include "peerinfo.h"
34
35static struct GNUNET_PEERINFO_IteratorContext *ic;
36
37static struct GNUNET_PEERINFO_Handle *h;
38
39static int global_ret;
40
41
42static int
43addr_cb (void *cls,
44 const struct GNUNET_HELLO_Address *address,
45 struct GNUNET_TIME_Absolute expiration)
46{
47 unsigned int *addr = cls;
48
49 (*addr)++;
50 return GNUNET_OK;
51}
52
53
54static void
55process (void *cls,
56 const struct GNUNET_PeerIdentity *peer,
57 const struct GNUNET_HELLO_Message *hello,
58 const char *err_msg)
59{
60 static unsigned int calls = 0;
61 unsigned int addr;
62
63 if (NULL != err_msg)
64 {
65 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
66 "Error in communication with PEERINFO service: %s\n",
67 err_msg);
68 }
69 if (NULL != peer)
70 {
71 addr = 0;
72 if (NULL != hello)
73 {
74 GNUNET_HELLO_iterate_addresses (hello,
75 GNUNET_NO,
76 &addr_cb,
77 &addr);
78 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
79 "Got information about peer %s with %u addresses\n",
80 GNUNET_i2s (peer),
81 addr);
82 calls++;
83 }
84 else
85 {
86 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
87 "Got no HELLP for peer %s\n",
88 GNUNET_i2s (peer));
89 }
90 }
91 else
92 {
93 if (0 == calls)
94 {
95 fprintf (stderr,
96 "Failed: got no callbacks!\n");
97 global_ret = 1;
98 GNUNET_PEERINFO_disconnect (h);
99 h = NULL;
100 }
101 else
102 {
103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
104 "Got %u HELLOs in total\n",
105 calls);
106 global_ret = 0;
107 GNUNET_PEERINFO_disconnect (h);
108 h = NULL;
109 }
110 }
111}
112
113
114static void
115run (void *cls,
116 const struct GNUNET_CONFIGURATION_Handle *cfg,
117 struct GNUNET_TESTING_Peer *peer)
118{
119 h = GNUNET_PEERINFO_connect (cfg);
120 GNUNET_assert (NULL != h);
121 ic = GNUNET_PEERINFO_iterate (h,
122 GNUNET_YES,
123 NULL,
124 &process,
125 cls);
126 GNUNET_assert (NULL != ic);
127}
128
129
130int
131main (int argc,
132 char *argv[])
133{
134 global_ret = 3;
135 if (0 != GNUNET_TESTING_service_run ("test_peerinfo_shipped_hellos",
136 "peerinfo",
137 "test_peerinfo_api_data.conf",
138 &run, NULL))
139 return 1;
140 return global_ret;
141}
142
143
144/* end of test_peerinfo_shipped_hellos.c */