GNUnet  0.11.x
gnunet-service-peerinfo.c
Go to the documentation of this file.
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 
31 #include "platform.h"
32 #include "gnunet_util_lib.h"
33 #include "gnunet_hello_lib.h"
34 #include "gnunet_protocols.h"
36 #include "peerinfo.h"
37 
41 #define DATA_HOST_FREQ \
42  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
43 
47 #define DATA_HOST_CLEAN_FREQ \
48  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60)
49 
50 
54 struct HostEntry
55 {
60 
65 
70 };
71 
72 
77 {
82 
87 };
88 
89 
95 
100 
106 
110 static char *networkIdDirectory;
111 
116 
121 
126 
127 
136 static struct InfoMessage *
138 {
139  struct InfoMessage *im;
140  struct GNUNET_HELLO_Message *src;
141  size_t hs;
142 
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));
151  im->peer = he->identity;
152  GNUNET_memcpy (&im[1], src, hs);
153  return im;
154 }
155 
156 
165 static int
166 discard_expired (void *cls,
167  const struct GNUNET_HELLO_Address *address,
169 {
170  const struct GNUNET_TIME_Absolute *now = cls;
171 
172  if (now->abs_value_us > expiration.abs_value_us)
173  {
175  _ ("Removing expired address of transport `%s'\n"),
176  address->transport_name);
177  return GNUNET_NO;
178  }
179  return GNUNET_OK;
180 }
181 
182 
191 static int
192 count_addresses (void *cls,
193  const struct GNUNET_HELLO_Address *address,
195 {
196  unsigned int *cnt = cls;
197 
198  (void) address;
199  (void) expiration;
200  (*cnt)++;
201  return GNUNET_OK;
202 }
203 
204 
212 static char *
214 {
215  char *fn;
216 
217  if (NULL == networkIdDirectory)
218  return NULL;
219  GNUNET_asprintf (&fn,
220  "%s%s%s",
223  GNUNET_i2s_full (id));
224  return fn;
225 }
226 
227 
234 static void
235 notify_all (struct HostEntry *entry)
236 {
237  struct InfoMessage *msg_pub;
238  struct InfoMessage *msg_friend;
239 
241  "Notifying all clients about peer `%s'\n",
242  GNUNET_i2s (&entry->identity));
243  msg_pub = make_info_message (entry, GNUNET_NO);
245  &msg_pub->header,
246  GNUNET_NO);
247  GNUNET_free (msg_pub);
248  msg_friend = make_info_message (entry, GNUNET_YES);
250  &msg_friend->header,
251  GNUNET_NO);
252  GNUNET_free (msg_friend);
253 }
254 
255 
262 static void
263 update_hello (const struct GNUNET_PeerIdentity *peer,
264  const struct GNUNET_HELLO_Message *hello);
265 
266 
278 static void
279 read_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));
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  {
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))
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  {
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))
330  }
331  else
332  {
333  if ((GNUNET_YES == unlink_garbage) && (0 != truncate (fn, read_pos)) &&
334  (ENOENT != errno))
336  }
337  return;
338  }
339 
340  now = GNUNET_TIME_absolute_get ();
341  hello_clean = GNUNET_HELLO_iterate_addresses (hello,
342  GNUNET_YES,
344  &now);
345  if (NULL == hello_clean)
346  {
348  _ ("Failed to parse HELLO in file `%s'\n"),
349  fn);
350  if ((GNUNET_YES == unlink_garbage) && (0 != unlink (fn)) &&
351  (ENOENT != errno))
353  return;
354  }
355  left = 0;
356  (void) GNUNET_HELLO_iterate_addresses (hello_clean,
357  GNUNET_NO,
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);
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)))
397  }
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 
412 static struct HostEntry *
414 {
415  struct HostEntry *entry;
416  struct ReadHostFileContext r;
417  char *fn;
418 
420  if (NULL == entry)
421  {
423  "Adding new peer `%s'\n",
424  GNUNET_i2s (identity));
426  gettext_noop ("# peers known"),
427  1,
428  GNUNET_NO);
429  entry = GNUNET_new (struct HostEntry);
430  entry->identity = *identity;
433  hostmap,
434  &entry->identity,
435  entry,
437  notify_all (entry);
439  if (NULL != fn)
440  {
441  read_host_file (fn, GNUNET_YES, &r);
442  if (NULL != r.hello)
444  if (NULL != r.friend_only_hello)
446  GNUNET_free (r.hello);
448  GNUNET_free (fn);
449  }
450  }
451  return entry;
452 }
453 
454 
461 static void
462 remove_garbage (const char *fullname)
463 {
464  if (0 == unlink (fullname))
465  GNUNET_log (
467  _ (
468  "File `%s' in directory `%s' does not match naming convention. Removed.\n"),
469  fullname,
471  else
473  "unlink",
474  fullname);
475 }
476 
477 
482 {
489 
494  unsigned int matched;
495 };
496 
497 
507 static int
508 hosts_directory_scan_callback (void *cls, const char *fullname)
509 {
510  struct DirScanContext *dsc = cls;
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 ==
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 */
577  if (NULL != r.hello)
578  {
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  {
588  "Updating peer `%s' friend only HELLO \n",
589  GNUNET_i2s (&id));
592  }
593  dsc->matched++;
594  return GNUNET_OK;
595 }
596 
597 
603 static void
605 {
606  static unsigned int retries;
607  struct DirScanContext dsc;
608 
609  (void) cls;
610  cron_scan = NULL;
612  {
613  cron_scan =
616  &
618  NULL);
619  return;
620  }
621  dsc.matched = 0;
622  dsc.remove_files = GNUNET_YES;
624  _ ("Scanning directory `%s'\n"),
628  &dsc);
629  if ((0 == dsc.matched) && (0 == (++retries & 31)))
631  _ ("Still no peers found in `%s'!\n"),
633  cron_scan =
637  NULL);
638 }
639 
640 
648 static struct GNUNET_HELLO_Message *
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);
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);
672  return res;
673 }
674 
675 
682 static void
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;
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 
700  GNUNET_assert (NULL != host);
701 
702  friend_hello_type = GNUNET_HELLO_is_friend_only (hello);
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);
727  if (delta.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
728  {
729  /* no differences, just ignore the update */
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)
747  host->friend_only_hello = mrg;
748  }
749 
750  if (NULL != host->hello)
752  if (NULL != host->friend_only_hello)
753  GNUNET_assert (
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)
764  GNUNET_NO,
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)
775  GNUNET_NO,
777  &cnt);
778  store_friend_hello = GNUNET_NO;
779  if (0 < cnt)
780  {
781  store_friend_hello = GNUNET_YES;
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,
806  pos += GNUNET_HELLO_size (host->friend_only_hello);
807  }
808  GNUNET_assert (pos == size);
809 
810  if (GNUNET_SYSERR ==
812  buffer,
813  size,
819  else
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 
838 {
843 
848 };
849 
850 
859 static int
860 add_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));
876  GNUNET_memcpy (&im[1], pos->hello, hs);
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 */
886  GNUNET_assert (hs < GNUNET_MAX_MESSAGE_SIZE - sizeof(struct InfoMessage));
888  GNUNET_memcpy (&im[1], pos->friend_only_hello, hs);
890  "Sending friend-only HELLO with size %u for peer `%s'\n",
891  hs,
892  GNUNET_i2s (key));
893  }
894  else
895  {
898  "Adding no HELLO for peer `%s'\n",
899  GNUNET_i2s (key));
900  }
901  im->peer = pos->identity;
903  return GNUNET_YES;
904 }
905 
906 
914 static int
915 discard_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 
931  {
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))
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))
965  "unlink",
966  fn);
967  GNUNET_free (writebuffer);
968  return GNUNET_OK;
969  }
970  new_hello =
972  cnt = 0;
973  if (NULL != new_hello)
974  (void) GNUNET_HELLO_iterate_addresses (hello,
975  GNUNET_NO,
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);
994  writebuffer,
995  write_pos,
1000  }
1001  else if (0 != unlink (fn))
1004  "unlink",
1005  fn);
1006 
1007  GNUNET_free (writebuffer);
1008  return GNUNET_OK;
1009 }
1010 
1011 
1018 static void
1020 {
1021  struct GNUNET_TIME_Absolute now;
1022 
1023  (void) cls;
1024  cron_clean = NULL;
1025  now = GNUNET_TIME_absolute_get ();
1027  _ ("Cleaning up directory `%s'\n"),
1032  NULL);
1033 }
1034 
1035 
1043 static int
1044 check_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 
1064 static void
1065 handle_hello (void *cls, const struct GNUNET_HELLO_Message *hello)
1066 {
1067  struct GNUNET_SERVICE_Client *client = cls;
1068  struct GNUNET_PeerIdentity pid;
1069 
1072  "HELLO message received for peer `%s'\n",
1073  GNUNET_i2s (&pid));
1075  update_hello (&pid, hello);
1077 }
1078 
1079 
1086 static void
1087 handle_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 
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;
1100  &lpm->peer,
1101  &add_to_tc,
1102  &tcx);
1106 }
1107 
1108 
1115 static void
1116 handle_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;
1130 }
1131 
1132 
1139 static void
1140 handle_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);
1151  if (ntohl (nm->include_friend_only))
1153  else
1155  tcx.friend_only = ntohl (nm->include_friend_only);
1156  tcx.client = client;
1161 }
1162 
1163 
1172 static void *
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 
1190 static void
1192  struct GNUNET_SERVICE_Client *client,
1193  void *app_ctx)
1194 {
1195  (void) cls;
1196  GNUNET_assert (app_ctx == client);
1197 }
1198 
1199 
1208 static int
1209 free_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);
1217  GNUNET_free (he);
1218  return GNUNET_YES;
1219 }
1220 
1221 
1227 static void
1228 shutdown_task (void *cls)
1229 {
1230  (void) cls;
1232  notify_list = NULL;
1234  notify_friend_only_list = NULL;
1235 
1238  if (NULL != stats)
1239  {
1241  stats = NULL;
1242  }
1243  if (NULL != cron_clean)
1244  {
1246  cron_clean = NULL;
1247  }
1248  if (NULL != cron_scan)
1249  {
1251  cron_scan = NULL;
1252  }
1253  if (NULL != networkIdDirectory)
1254  {
1256  networkIdDirectory = NULL;
1257  }
1258 }
1259 
1260 
1268 static void
1269 run (void *cls,
1270  const struct GNUNET_CONFIGURATION_Handle *cfg,
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;
1282  stats = GNUNET_STATISTICS_create ("peerinfo", cfg);
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;
1292  if (GNUNET_YES != noio)
1293  {
1294  GNUNET_assert (
1295  GNUNET_OK ==
1297  "peerinfo",
1298  "HOSTS",
1299  &networkIdDirectory));
1301  {
1303  return;
1304  }
1305 
1306  cron_scan =
1309  NULL);
1310 
1311  cron_clean =
1314  NULL);
1315  if (GNUNET_YES == use_included)
1316  {
1318  GNUNET_asprintf (&peerdir, "%shellos", ip);
1319  GNUNET_free (ip);
1320 
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,
1329  &dsc);
1330  GNUNET_free (peerdir);
1331  }
1332  else
1333  {
1335  _ ("Skipping import of included HELLOs\n"));
1336  }
1337  }
1338 }
1339 
1340 
1345  "peerinfo",
1347  &run,
1350  NULL,
1351  GNUNET_MQ_hd_var_size (hello,
1353  struct GNUNET_HELLO_Message,
1354  NULL),
1357  struct ListPeerMessage,
1358  NULL),
1359  GNUNET_MQ_hd_fixed_size (get_all,
1361  struct ListAllPeersMessage,
1362  NULL),
1365  struct NotifyMessage,
1366  NULL),
1368 
1369 
1370 /* end of gnunet-service-peerinfo.c */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define gettext_noop(String)
Definition: gettext.h:69
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int res
static char * address
GNS address for this phone.
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
static struct GNUNET_PEERINFO_NotifyContext * notify
Handle to the peerinfo notify service (NULL until we've connected to it).
struct GNUNET_HashCode key
The key used in the DHT.
static char * filename
static char * value
Value of the record to add/remove.
static int include_friend_only
Option '-f'.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static char * networkIdDirectory
Directory where the hellos are stored in (peerinfo/)
static void handle_notify(void *cls, const struct NotifyMessage *nm)
Handle NOTIFY-message.
static struct InfoMessage * make_info_message(const struct HostEntry *he, int include_friend_only)
Notify all clients in the notify list about the given host entry changing.
static void handle_get(void *cls, const struct ListPeerMessage *lpm)
Handle GET-message.
static void cron_clean_data_hosts(void *cls)
Call this method periodically to scan peerinfo/ for ancient HELLOs to expire.
static struct GNUNET_SCHEDULER_Task * cron_scan
Handle for task to run cron_scan_directory_data_hosts()
#define DATA_HOST_CLEAN_FREQ
How often do we discard old entries in data/hosts/?
static int discard_hosts_helper(void *cls, const char *fn)
delete expired HELLO entries in directory
static int hosts_directory_scan_callback(void *cls, const char *fullname)
Function that is called on each HELLO file in a particular directory.
static struct GNUNET_STATISTICS_Handle * stats
Handle for reporting statistics.
static int check_hello(void *cls, const struct GNUNET_HELLO_Message *hello)
Check HELLO-message.
static struct GNUNET_NotificationContext * notify_list
Clients to immediately notify about all changes.
static void notify_all(struct HostEntry *entry)
Broadcast information about the given entry to all clients that care.
static void shutdown_task(void *cls)
Clean up our state.
static struct GNUNET_HELLO_Message * update_friend_hello(const struct GNUNET_HELLO_Message *hello, const struct GNUNET_HELLO_Message *friend_hello)
Update the HELLO of a friend by merging the addresses.
static int free_host_entry(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Release memory taken by a host entry.
static void cron_scan_directory_data_hosts(void *cls)
Call this method periodically to scan data/hosts for new hosts.
static char * get_host_filename(const struct GNUNET_PeerIdentity *id)
Get the filename under which we would store the GNUNET_HELLO_Message for the given host and protocol.
static int add_to_tc(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Do transmit info about peer to given host.
static void read_host_file(const char *fn, int unlink_garbage, struct ReadHostFileContext *r)
Try to read the HELLOs in the given filename and discard expired addresses.
static void update_hello(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello)
Bind a host address (hello) to a hostId.
GNUNET_SERVICE_MAIN("peerinfo", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(hello, GNUNET_MESSAGE_TYPE_HELLO, struct GNUNET_HELLO_Message, NULL), GNUNET_MQ_hd_fixed_size(get, GNUNET_MESSAGE_TYPE_PEERINFO_GET, struct ListPeerMessage, NULL), GNUNET_MQ_hd_fixed_size(get_all, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL, struct ListAllPeersMessage, NULL), GNUNET_MQ_hd_fixed_size(notify, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY, struct NotifyMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static void remove_garbage(const char *fullname)
Remove a file that should not be there.
static int count_addresses(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Address iterator that counts the remaining addresses.
static struct HostEntry * add_host_to_known_hosts(const struct GNUNET_PeerIdentity *identity)
Add a host to the list and notify clients about this event.
static struct GNUNET_NotificationContext * notify_friend_only_list
Clients to immediately notify about all changes, even for friend-only HELLOs.
static int discard_expired(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Address iterator that causes expired entries to be discarded.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Client connect callback.
static struct GNUNET_SCHEDULER_Task * cron_clean
Handle for task to run cron_clean_data_hosts()
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Client disconnect callback.
static void handle_hello(void *cls, const struct GNUNET_HELLO_Message *hello)
Handle HELLO-message.
static struct GNUNET_CONTAINER_MultiPeerMap * hostmap
The in-memory list of known hosts, mapping of host IDs to 'struct HostEntry*' values.
static void handle_get_all(void *cls, const struct ListAllPeersMessage *lapm)
Handle GET-ALL-message.
#define DATA_HOST_FREQ
How often do we scan the HOST_DIR for new entries?
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *service)
Start up peerinfo service.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
#define GNUNET_log(kind,...)
@ GNUNET_SCHEDULER_PRIORITY_IDLE
Run when otherwise idle.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_public_key_from_string(const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a string representing a public key to a public key.
Definition: crypto_ecc.c:357
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition: disk.c:482
enum GNUNET_GenericReturnValue GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:222
enum GNUNET_GenericReturnValue GNUNET_DISK_fn_write(const char *fn, const void *buf, size_t buf_size, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file atomically.
Definition: disk.c:725
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1085
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:496
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:664
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:814
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_GROUP_READ
Group can read.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
@ GNUNET_DISK_PERM_OTHER_READ
Everybody can read.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
int GNUNET_HELLO_get_id(const struct GNUNET_HELLO_Message *hello, struct GNUNET_PeerIdentity *peer)
Get the peer identity from a HELLO message.
Definition: hello.c:671
uint16_t GNUNET_HELLO_size(const struct GNUNET_HELLO_Message *hello)
Return the size of the given HELLO message.
Definition: hello.c:652
struct GNUNET_HELLO_Message * GNUNET_HELLO_create(const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, GNUNET_HELLO_GenerateAddressListCallback addrgen, void *addrgen_cls, int friend_only)
Construct a HELLO message given the public key, expiration time and an iterator that spews the transp...
Definition: hello.c:204
struct GNUNET_HELLO_Message * GNUNET_HELLO_merge(const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2)
Construct a HELLO message by merging the addresses in two existing HELLOs (which must be for the same...
Definition: hello.c:524
int GNUNET_HELLO_is_friend_only(const struct GNUNET_HELLO_Message *h)
Return HELLO type.
Definition: hello.c:89
struct GNUNET_TIME_Absolute GNUNET_HELLO_equals(const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2, struct GNUNET_TIME_Absolute now)
Test if two HELLO messages contain the same addresses.
Definition: hello.c:834
struct GNUNET_HELLO_Message * GNUNET_HELLO_iterate_addresses(const struct GNUNET_HELLO_Message *msg, int return_modified, GNUNET_HELLO_AddressIterator it, void *it_cls)
Iterate over all of the addresses in the HELLO.
Definition: hello.c:254
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:137
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:355
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:52
void GNUNET_notification_context_broadcast(struct GNUNET_NotificationContext *nc, const struct GNUNET_MessageHeader *msg, int can_drop)
Send a message to all subscribers of this context.
Definition: nc.c:189
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:121
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:160
char * GNUNET_OS_installation_get_path(enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
@ GNUNET_OS_IPK_DATADIR
Return the directory where data is installed (share/gnunet/)
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END
End of information about other peers.
#define GNUNET_MESSAGE_TYPE_PEERINFO_GET
Request update and listing of a peer.
#define GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL
Request update and listing of all peers.
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO
Information about one of the peers.
#define GNUNET_MESSAGE_TYPE_HELLO
HELLO message with friend only flag used for communicating peer addresses.
#define GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY
Start notifying this client about all changes to the known peers until it disconnects.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1199
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition: scheduler.c:1223
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1331
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2408
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2438
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2244
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition: peer.c:67
common internal definitions for peerinfo service
#define DIR_SEPARATOR
Definition: platform.h:164
#define DIR_SEPARATOR_STR
Definition: platform.h:165
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:423
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:35
Closure for hosts_directory_scan_callback().
int remove_files
GNUNET_YES if we should remove files that are broken, GNUNET_NO if the directory we are iterating ove...
unsigned int matched
Counter for the number of (valid) entries found, incremented by one for each match.
Internal representation of the hash map.
An address for communicating with a peer.
A HELLO message is used to exchange information about transports with other peers.
Handle to a message queue.
Definition: mq.c:86
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition: nc.c:76
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition: scheduler.c:135
Handle to a client that is connected to a service.
Definition: service.c:251
Handle to a service.
Definition: service.c:117
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
In-memory cache of known hosts.
struct GNUNET_HELLO_Message * hello
Hello for the peer (can be NULL)
struct GNUNET_PeerIdentity identity
Identity of the peer.
struct GNUNET_HELLO_Message * friend_only_hello
Friend only hello for the peer (can be NULL)
Message used to inform the client about a particular peer; this message is optionally followed by a H...
Definition: peerinfo.h:103
struct GNUNET_PeerIdentity peer
About which peer are we talking here?
Definition: peerinfo.h:117
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_PEERINFO_INFO.
Definition: peerinfo.h:107
Message requesting a listing of all peers, restricted to the specified peer identity.
Definition: peerinfo.h:65
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:74
Message requesting a listing of peers, restricted to the specified peer identity.
Definition: peerinfo.h:42
struct GNUNET_PeerIdentity peer
Restrict to peers with this identity (optional field, check header.size!).
Definition: peerinfo.h:57
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:51
Header for all communications.
Definition: peerinfo.h:82
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:91
Result of reading a file.
struct GNUNET_HELLO_Message * friend_only_hello
Friend only hello for the peer (can be NULL)
struct GNUNET_HELLO_Message * hello
Hello for the peer (can be NULL)
Closure for add_to_tc()
struct GNUNET_SERVICE_Client * client
Client to transmit to.
int friend_only
Include friend only HELLOs GNUNET_YES or GNUNET_NO.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.