GNUnet  0.10.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 {
59 
64 
69 };
70 
71 
80 
85 };
86 
87 
93 
98 
104 
108 static char *networkIdDirectory;
109 
114 
119 
124 
125 
134 static struct InfoMessage *
136 {
137  struct InfoMessage *im;
138  struct GNUNET_HELLO_Message *src;
139  size_t hs;
140 
141  if (GNUNET_YES == include_friend_only)
142  src = he->friend_only_hello;
143  else
144  src = he->hello;
145  hs = (NULL == src) ? 0 : GNUNET_HELLO_size(src);
146  im = GNUNET_malloc(sizeof(struct InfoMessage) + hs);
147  im->header.size = htons(hs + sizeof(struct InfoMessage));
149  im->peer = he->identity;
150  GNUNET_memcpy(&im[1], src, hs);
151  return im;
152 }
153 
154 
163 static int
164 discard_expired(void *cls,
165  const struct GNUNET_HELLO_Address *address,
167 {
168  const struct GNUNET_TIME_Absolute *now = cls;
169 
170  if (now->abs_value_us > expiration.abs_value_us)
171  {
173  _("Removing expired address of transport `%s'\n"),
174  address->transport_name);
175  return GNUNET_NO;
176  }
177  return GNUNET_OK;
178 }
179 
180 
189 static int
190 count_addresses(void *cls,
191  const struct GNUNET_HELLO_Address *address,
193 {
194  unsigned int *cnt = cls;
195 
196  (void)address;
197  (void)expiration;
198  (*cnt)++;
199  return GNUNET_OK;
200 }
201 
202 
210 static char *
212 {
213  char *fn;
214 
215  if (NULL == networkIdDirectory)
216  return NULL;
217  GNUNET_asprintf(&fn,
218  "%s%s%s",
221  GNUNET_i2s_full(id));
222  return fn;
223 }
224 
225 
232 static void
233 notify_all(struct HostEntry *entry)
234 {
235  struct InfoMessage *msg_pub;
236  struct InfoMessage *msg_friend;
237 
239  "Notifying all clients about peer `%s'\n",
240  GNUNET_i2s(&entry->identity));
241  msg_pub = make_info_message(entry, GNUNET_NO);
243  &msg_pub->header,
244  GNUNET_NO);
245  GNUNET_free(msg_pub);
246  msg_friend = make_info_message(entry, GNUNET_YES);
247  GNUNET_notification_context_broadcast(notify_friend_only_list,
248  &msg_friend->header,
249  GNUNET_NO);
250  GNUNET_free(msg_friend);
251 }
252 
253 
260 static void
262  const struct GNUNET_HELLO_Message *hello);
263 
264 
276 static void
277 read_host_file(const char *fn,
278  int unlink_garbage,
279  struct ReadHostFileContext *r)
280 {
281  char buffer[GNUNET_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
282  ssize_t size_total;
283  struct GNUNET_TIME_Absolute now;
284  unsigned int left;
285  const struct GNUNET_HELLO_Message *hello;
286  struct GNUNET_HELLO_Message *hello_clean;
287  size_t read_pos;
288  uint16_t size_hello;
289 
290  r->friend_only_hello = NULL;
291  r->hello = NULL;
292 
294  return;
295  size_total = GNUNET_DISK_fn_read(fn, buffer, sizeof(buffer));
297  "Read %d bytes from `%s'\n",
298  (int)size_total,
299  fn);
300  if ((size_total < 0) ||
301  (((size_t)size_total) < sizeof(struct GNUNET_MessageHeader)))
302  {
304  _("Failed to parse HELLO in file `%s': %s\n"),
305  fn,
306  "File has invalid size");
307  if ((GNUNET_YES == unlink_garbage) && (0 != unlink(fn)) &&
308  (ENOENT != errno))
310  return;
311  }
312 
313  read_pos = 0;
314  while (read_pos < (size_t)size_total)
315  {
316  hello = (const struct GNUNET_HELLO_Message *)&buffer[read_pos];
317  size_hello = GNUNET_HELLO_size(hello);
318  if ((0 == size_hello) || (((size_t)size_total) - read_pos < size_hello))
319  {
321  _("Failed to parse HELLO in file `%s'\n"),
322  fn);
323  if (0 == read_pos)
324  {
325  if ((GNUNET_YES == unlink_garbage) && (0 != unlink(fn)) &&
326  (ENOENT != errno))
328  }
329  else
330  {
331  if ((GNUNET_YES == unlink_garbage) && (0 != truncate(fn, read_pos)) &&
332  (ENOENT != errno))
334  }
335  return;
336  }
337 
338  now = GNUNET_TIME_absolute_get();
339  hello_clean = GNUNET_HELLO_iterate_addresses(hello,
340  GNUNET_YES,
342  &now);
343  if (NULL == hello_clean)
344  {
346  _("Failed to parse HELLO in file `%s'\n"),
347  fn);
348  if ((GNUNET_YES == unlink_garbage) && (0 != unlink(fn)) &&
349  (ENOENT != errno))
351  return;
352  }
353  left = 0;
354  (void)GNUNET_HELLO_iterate_addresses(hello_clean,
355  GNUNET_NO,
357  &left);
358 
359  if (0 == left)
360  {
361  GNUNET_free(hello_clean);
362  break;
363  }
364 
365  if (GNUNET_NO == GNUNET_HELLO_is_friend_only(hello_clean))
366  {
367  if (NULL == r->hello)
368  r->hello = hello_clean;
369  else
370  {
371  GNUNET_break(0);
372  GNUNET_free(r->hello);
373  r->hello = hello_clean;
374  }
375  }
376  else
377  {
378  if (NULL == r->friend_only_hello)
379  r->friend_only_hello = hello_clean;
380  else
381  {
382  GNUNET_break(0);
384  r->friend_only_hello = hello_clean;
385  }
386  }
387  read_pos += size_hello;
388  }
389 
390  if (0 == left)
391  {
392  /* no addresses left, remove from disk */
393  if ((GNUNET_YES == unlink_garbage) && (0 != unlink(fn)))
395  }
397  "Found `%s' and `%s' HELLO message in file\n",
398  (NULL != r->hello) ? "public" : "NON-public",
399  (NULL != r->friend_only_hello) ? "friend only"
400  : "NO friend only");
401 }
402 
403 
410 static struct HostEntry *
412 {
413  struct HostEntry *entry;
414  struct ReadHostFileContext r;
415  char *fn;
416 
417  entry = GNUNET_CONTAINER_multipeermap_get(hostmap, identity);
418  if (NULL == entry)
419  {
421  "Adding new peer `%s'\n",
422  GNUNET_i2s(identity));
424  gettext_noop("# peers known"),
425  1,
426  GNUNET_NO);
427  entry = GNUNET_new(struct HostEntry);
428  entry->identity = *identity;
431  hostmap,
432  &entry->identity,
433  entry,
435  notify_all(entry);
436  fn = get_host_filename(identity);
437  if (NULL != fn)
438  {
439  read_host_file(fn, GNUNET_YES, &r);
440  if (NULL != r.hello)
441  update_hello(identity, r.hello);
442  if (NULL != r.friend_only_hello)
443  update_hello(identity, r.friend_only_hello);
446  GNUNET_free(fn);
447  }
448  }
449  return entry;
450 }
451 
452 
459 static void
460 remove_garbage(const char *fullname)
461 {
462  if (0 == unlink(fullname))
463  GNUNET_log(
465  _(
466  "File `%s' in directory `%s' does not match naming convention. Removed.\n"),
467  fullname,
469  else
471  "unlink",
472  fullname);
473 }
474 
475 
486 
491  unsigned int matched;
492 };
493 
494 
504 static int
505 hosts_directory_scan_callback(void *cls, const char *fullname)
506 {
507  struct DirScanContext *dsc = cls;
508  struct GNUNET_PeerIdentity identity;
509  struct ReadHostFileContext r;
510  const char *filename;
511  struct GNUNET_PeerIdentity id_public;
512  struct GNUNET_PeerIdentity id_friend;
513  struct GNUNET_PeerIdentity id;
514 
515  if (GNUNET_YES != GNUNET_DISK_file_test(fullname))
516  return GNUNET_OK; /* ignore non-files */
517 
518  filename = strrchr(fullname, DIR_SEPARATOR);
519  if ((NULL == filename) || (1 > strlen(filename)))
520  filename = fullname;
521  else
522  filename++;
523 
524  read_host_file(fullname, dsc->remove_files, &r);
525  if ((NULL == r.hello) && (NULL == r.friend_only_hello))
526  return GNUNET_OK;
527  if (NULL != r.friend_only_hello)
528  {
529  if (GNUNET_OK != GNUNET_HELLO_get_id(r.friend_only_hello, &id_friend))
530  {
531  if (GNUNET_YES == dsc->remove_files)
532  remove_garbage(fullname);
533  return GNUNET_OK;
534  }
535  id = id_friend;
536  }
537  if (NULL != r.hello)
538  {
539  if (GNUNET_OK != GNUNET_HELLO_get_id(r.hello, &id_public))
540  {
541  if (GNUNET_YES == dsc->remove_files)
542  remove_garbage(fullname);
543  return GNUNET_OK;
544  }
545  id = id_public;
546  }
547 
548  if ((NULL != r.hello) && (NULL != r.friend_only_hello) &&
549  (0 != GNUNET_memcmp(&id_friend, &id_public)))
550  {
551  /* HELLOs are not for the same peer */
552  GNUNET_break(0);
553  if (GNUNET_YES == dsc->remove_files)
554  remove_garbage(fullname);
555  return GNUNET_OK;
556  }
557  if (GNUNET_OK ==
559  strlen(filename),
560  &identity.public_key))
561  {
562  if (0 != GNUNET_memcmp(&id, &identity))
563  {
564  /* HELLOs are not for the same peer */
565  GNUNET_break(0);
566  if (GNUNET_YES == dsc->remove_files)
567  remove_garbage(fullname);
568  return GNUNET_OK;
569  }
570  }
571 
572  /* ok, found something valid, remember HELLO */
574  if (NULL != r.hello)
575  {
577  "Updating peer `%s' public HELLO \n",
578  GNUNET_i2s(&id));
579  update_hello(&id, r.hello);
580  GNUNET_free(r.hello);
581  }
582  if (NULL != r.friend_only_hello)
583  {
585  "Updating peer `%s' friend only HELLO \n",
586  GNUNET_i2s(&id));
589  }
590  dsc->matched++;
591  return GNUNET_OK;
592 }
593 
594 
600 static void
602 {
603  static unsigned int retries;
604  struct DirScanContext dsc;
605 
606  (void)cls;
607  cron_scan = NULL;
609  {
610  cron_scan =
614  NULL);
615  return;
616  }
617  dsc.matched = 0;
618  dsc.remove_files = GNUNET_YES;
620  _("Scanning directory `%s'\n"),
624  &dsc);
625  if ((0 == dsc.matched) && (0 == (++retries & 31)))
627  _("Still no peers found in `%s'!\n"),
629  cron_scan =
633  NULL);
634 }
635 
636 
644 static struct GNUNET_HELLO_Message *
646  const struct GNUNET_HELLO_Message *friend_hello)
647 {
648  struct GNUNET_HELLO_Message *res;
649  struct GNUNET_HELLO_Message *tmp;
650  struct GNUNET_PeerIdentity pid;
651 
652  if (NULL != friend_hello)
653  {
654  res = GNUNET_HELLO_merge(hello, friend_hello);
656  return res;
657  }
658 
659  if (GNUNET_OK != GNUNET_HELLO_get_id(hello, &pid))
660  {
661  GNUNET_break(0);
662  return NULL;
663  }
664  tmp = GNUNET_HELLO_create(&pid.public_key, NULL, NULL, GNUNET_YES);
665  res = GNUNET_HELLO_merge(hello, tmp);
666  GNUNET_free(tmp);
668  return res;
669 }
670 
671 
678 static void
680  const struct GNUNET_HELLO_Message *hello)
681 {
682  char *fn;
683  struct HostEntry *host;
684  struct GNUNET_HELLO_Message *mrg;
685  struct GNUNET_HELLO_Message **dest;
686  struct GNUNET_TIME_Absolute delta;
687  unsigned int cnt;
688  unsigned int size;
689  int friend_hello_type;
690  int store_hello;
691  int store_friend_hello;
692  unsigned int pos;
693  char *buffer;
694 
695  host = GNUNET_CONTAINER_multipeermap_get(hostmap, peer);
696  GNUNET_assert(NULL != host);
697 
698  friend_hello_type = GNUNET_HELLO_is_friend_only(hello);
700  "Updating %s HELLO for `%s'\n",
701  (GNUNET_YES == friend_hello_type) ? "friend-only" : "public",
702  GNUNET_i2s(peer));
703 
704  dest = NULL;
705  if (GNUNET_YES == friend_hello_type)
706  {
707  dest = &host->friend_only_hello;
708  }
709  else
710  {
711  dest = &host->hello;
712  }
713 
714  if (NULL == (*dest))
715  {
716  (*dest) = GNUNET_malloc(GNUNET_HELLO_size(hello));
717  GNUNET_memcpy((*dest), hello, GNUNET_HELLO_size(hello));
718  }
719  else
720  {
721  mrg = GNUNET_HELLO_merge((*dest), hello);
722  delta = GNUNET_HELLO_equals(mrg, (*dest), GNUNET_TIME_absolute_get());
723  if (delta.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
724  {
725  /* no differences, just ignore the update */
727  "No change in %s HELLO for `%s'\n",
728  (GNUNET_YES == friend_hello_type) ? "friend-only" : "public",
729  GNUNET_i2s(peer));
730  GNUNET_free(mrg);
731  return;
732  }
733  GNUNET_free((*dest));
734  (*dest) = mrg;
735  }
736 
737  if ((NULL != (host->hello)) && (GNUNET_NO == friend_hello_type))
738  {
739  /* Update friend only hello */
740  mrg = update_friend_hello(host->hello, host->friend_only_hello);
741  if (NULL != host->friend_only_hello)
743  host->friend_only_hello = mrg;
744  }
745 
746  if (NULL != host->hello)
748  if (NULL != host->friend_only_hello)
751 
752  fn = get_host_filename(peer);
753  if ((NULL != fn) && (GNUNET_OK == GNUNET_DISK_directory_create_for_file(fn)))
754  {
755  store_hello = GNUNET_NO;
756  size = 0;
757  cnt = 0;
758  if (NULL != host->hello)
760  GNUNET_NO,
762  &cnt);
763  if (cnt > 0)
764  {
765  store_hello = GNUNET_YES;
766  size += GNUNET_HELLO_size(host->hello);
767  }
768  cnt = 0;
769  if (NULL != host->friend_only_hello)
771  GNUNET_NO,
773  &cnt);
774  store_friend_hello = GNUNET_NO;
775  if (0 < cnt)
776  {
777  store_friend_hello = GNUNET_YES;
778  size += GNUNET_HELLO_size(host->friend_only_hello);
779  }
780 
781  if ((GNUNET_NO == store_hello) && (GNUNET_NO == store_friend_hello))
782  {
783  /* no valid addresses, don't put HELLO on disk; in fact,
784  if one exists on disk, remove it */
785  (void)unlink(fn);
786  }
787  else
788  {
789  buffer = GNUNET_malloc(size);
790  pos = 0;
791 
792  if (GNUNET_YES == store_hello)
793  {
794  GNUNET_memcpy(buffer, host->hello, GNUNET_HELLO_size(host->hello));
795  pos += GNUNET_HELLO_size(host->hello);
796  }
797  if (GNUNET_YES == store_friend_hello)
798  {
799  GNUNET_memcpy(&buffer[pos],
800  host->friend_only_hello,
802  pos += GNUNET_HELLO_size(host->friend_only_hello);
803  }
804  GNUNET_assert(pos == size);
805 
807  buffer,
808  size,
814  else
816  "Stored %s %s HELLO in %s with total size %u\n",
817  (GNUNET_YES == store_friend_hello) ? "friend-only" : "",
818  (GNUNET_YES == store_hello) ? "public" : "",
819  fn,
820  size);
821  GNUNET_free(buffer);
822  }
823  }
825  notify_all(host);
826 }
827 
828 
837 
842 };
843 
844 
853 static int
854 add_to_tc(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
855 {
856  struct TransmitContext *tc = cls;
857  struct HostEntry *pos = value;
858  struct InfoMessage *im;
859  uint16_t hs;
860  struct GNUNET_MQ_Envelope *env;
861 
862  hs = 0;
863 
864  if ((NULL != pos->hello) && (GNUNET_NO == tc->friend_only))
865  {
866  /* Copy public HELLO */
867  hs = GNUNET_HELLO_size(pos->hello);
868  GNUNET_assert(hs < GNUNET_MAX_MESSAGE_SIZE - sizeof(struct InfoMessage));
870  GNUNET_memcpy(&im[1], pos->hello, hs);
872  "Sending public HELLO with size %u for peer `%s'\n",
873  hs,
874  GNUNET_i2s(key));
875  }
876  else if ((NULL != pos->friend_only_hello) && (GNUNET_YES == tc->friend_only))
877  {
878  /* Copy friend only HELLO */
880  GNUNET_assert(hs < GNUNET_MAX_MESSAGE_SIZE - sizeof(struct InfoMessage));
882  GNUNET_memcpy(&im[1], pos->friend_only_hello, hs);
884  "Sending friend-only HELLO with size %u for peer `%s'\n",
885  hs,
886  GNUNET_i2s(key));
887  }
888  else
889  {
892  "Adding no HELLO for peer `%s'\n",
893  GNUNET_i2s(key));
894  }
895  im->peer = pos->identity;
897  return GNUNET_YES;
898 }
899 
900 
908 static int
909 discard_hosts_helper(void *cls, const char *fn)
910 {
911  struct GNUNET_TIME_Absolute *now = cls;
912  char buffer[GNUNET_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
913  const struct GNUNET_HELLO_Message *hello;
914  struct GNUNET_HELLO_Message *new_hello;
915  int read_size;
916  unsigned int cur_hello_size;
917  unsigned int new_hello_size;
918  int read_pos;
919  int write_pos;
920  unsigned int cnt;
921  char *writebuffer;
922  uint64_t fsize;
923 
925  {
928  "fstat",
929  fn);
930  return GNUNET_OK;
931  }
932  read_size = GNUNET_DISK_fn_read(fn, buffer, sizeof(buffer));
933 
934  if ((read_size < (int)sizeof(struct GNUNET_MessageHeader)) ||
935  (fsize > GNUNET_MAX_MESSAGE_SIZE))
936  {
937  if (0 != unlink(fn))
940  "unlink",
941  fn);
942  return GNUNET_OK;
943  }
944 
945  writebuffer = GNUNET_malloc(read_size);
946  read_pos = 0;
947  write_pos = 0;
948  while (read_pos < read_size)
949  {
950  /* Check each HELLO */
951  hello = (const struct GNUNET_HELLO_Message *)&buffer[read_pos];
952  cur_hello_size = GNUNET_HELLO_size(hello);
953  if (0 == cur_hello_size)
954  {
955  /* Invalid data, discard */
956  if (0 != unlink(fn))
959  "unlink",
960  fn);
961  GNUNET_free(writebuffer);
962  return GNUNET_OK;
963  }
964  new_hello =
966  cnt = 0;
967  if (NULL != new_hello)
968  (void)GNUNET_HELLO_iterate_addresses(hello,
969  GNUNET_NO,
971  &cnt);
972  if ((NULL != new_hello) && (0 < cnt))
973  {
974  /* Store new HELLO to write it when done */
975  new_hello_size = GNUNET_HELLO_size(new_hello);
976  GNUNET_memcpy(&writebuffer[write_pos], new_hello, new_hello_size);
977  write_pos += new_hello_size;
978  }
979  read_pos += cur_hello_size;
980  GNUNET_free_non_null(new_hello);
981  }
982 
983  if (0 < write_pos)
984  {
986  writebuffer,
987  write_pos,
992  }
993  else if (0 != unlink(fn))
996  "unlink",
997  fn);
998 
999  GNUNET_free(writebuffer);
1000  return GNUNET_OK;
1001 }
1002 
1003 
1010 static void
1012 {
1013  struct GNUNET_TIME_Absolute now;
1014 
1015  (void)cls;
1016  cron_clean = NULL;
1017  now = GNUNET_TIME_absolute_get();
1019  _("Cleaning up directory `%s'\n"),
1024  NULL);
1025 }
1026 
1027 
1035 static int
1036 check_hello(void *cls, const struct GNUNET_HELLO_Message *hello)
1037 {
1038  struct GNUNET_PeerIdentity pid;
1039 
1040  (void)cls;
1041  if (GNUNET_OK != GNUNET_HELLO_get_id(hello, &pid))
1042  {
1043  GNUNET_break(0);
1044  return GNUNET_SYSERR;
1045  }
1046  return GNUNET_OK;
1047 }
1048 
1049 
1056 static void
1057 handle_hello(void *cls, const struct GNUNET_HELLO_Message *hello)
1058 {
1059  struct GNUNET_SERVICE_Client *client = cls;
1060  struct GNUNET_PeerIdentity pid;
1061 
1062  GNUNET_assert(GNUNET_OK == GNUNET_HELLO_get_id(hello, &pid));
1064  "HELLO message received for peer `%s'\n",
1065  GNUNET_i2s(&pid));
1067  update_hello(&pid, hello);
1069 }
1070 
1071 
1078 static void
1079 handle_get(void *cls, const struct ListPeerMessage *lpm)
1080 {
1081  struct GNUNET_SERVICE_Client *client = cls;
1082  struct TransmitContext tcx;
1083  struct GNUNET_MessageHeader *msg;
1084  struct GNUNET_MQ_Envelope *env;
1085 
1087  "GET message received for peer `%s'\n",
1088  GNUNET_i2s(&lpm->peer));
1089  tcx.friend_only = ntohl(lpm->include_friend_only);
1090  tcx.client = client;
1092  &lpm->peer,
1093  &add_to_tc,
1094  &tcx);
1098 }
1099 
1100 
1107 static void
1108 handle_get_all(void *cls, const struct ListAllPeersMessage *lapm)
1109 {
1110  struct GNUNET_SERVICE_Client *client = cls;
1111  struct TransmitContext tcx;
1112  struct GNUNET_MQ_Envelope *env;
1113  struct GNUNET_MessageHeader *msg;
1114 
1115  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GET_ALL message received\n");
1116  tcx.friend_only = ntohl(lapm->include_friend_only);
1117  tcx.client = client;
1122 }
1123 
1124 
1131 static void
1132 handle_notify(void *cls, const struct NotifyMessage *nm)
1133 {
1134  struct GNUNET_SERVICE_Client *client = cls;
1135  struct GNUNET_MQ_Handle *mq;
1136  struct TransmitContext tcx;
1137  struct GNUNET_MQ_Envelope *env;
1138  struct GNUNET_MessageHeader *msg;
1139 
1140  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "NOTIFY message received\n");
1141  mq = GNUNET_SERVICE_client_get_mq(client);
1143  if (ntohl(nm->include_friend_only))
1144  GNUNET_notification_context_add(notify_friend_only_list, mq);
1145  else
1146  GNUNET_notification_context_add(notify_list, mq);
1147  tcx.friend_only = ntohl(nm->include_friend_only);
1148  tcx.client = client;
1153 }
1154 
1155 
1164 static void *
1166  struct GNUNET_SERVICE_Client *client,
1167  struct GNUNET_MQ_Handle *mq)
1168 {
1169  (void)cls;
1170  (void)mq;
1171  return client;
1172 }
1173 
1174 
1182 static void
1184  struct GNUNET_SERVICE_Client *client,
1185  void *app_ctx)
1186 {
1187  (void)cls;
1188  GNUNET_assert(app_ctx == client);
1189 }
1190 
1191 
1200 static int
1201 free_host_entry(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
1202 {
1203  struct HostEntry *he = value;
1204 
1205  (void)cls;
1206  (void)key;
1209  GNUNET_free(he);
1210  return GNUNET_YES;
1211 }
1212 
1213 
1219 static void
1220 shutdown_task(void *cls)
1221 {
1222  (void)cls;
1224  notify_list = NULL;
1225  GNUNET_notification_context_destroy(notify_friend_only_list);
1226  notify_friend_only_list = NULL;
1227 
1230  if (NULL != stats)
1231  {
1233  stats = NULL;
1234  }
1235  if (NULL != cron_clean)
1236  {
1237  GNUNET_SCHEDULER_cancel(cron_clean);
1238  cron_clean = NULL;
1239  }
1240  if (NULL != cron_scan)
1241  {
1242  GNUNET_SCHEDULER_cancel(cron_scan);
1243  cron_scan = NULL;
1244  }
1245  if (NULL != networkIdDirectory)
1246  {
1248  networkIdDirectory = NULL;
1249  }
1250 }
1251 
1252 
1260 static void
1261 run(void *cls,
1262  const struct GNUNET_CONFIGURATION_Handle *cfg,
1264 {
1265  char *peerdir;
1266  char *ip;
1267  struct DirScanContext dsc;
1268  int noio;
1269  int use_included;
1270 
1271  (void)cls;
1272  (void)service;
1274  stats = GNUNET_STATISTICS_create("peerinfo", cfg);
1275  notify_list = GNUNET_notification_context_create(0);
1276  notify_friend_only_list = GNUNET_notification_context_create(0);
1277  noio = GNUNET_CONFIGURATION_get_value_yesno(cfg, "peerinfo", "NO_IO");
1278  use_included = GNUNET_CONFIGURATION_get_value_yesno(cfg,
1279  "peerinfo",
1280  "USE_INCLUDED_HELLOS");
1281  if (GNUNET_SYSERR == use_included)
1282  use_included = GNUNET_NO;
1284  if (GNUNET_YES != noio)
1285  {
1286  GNUNET_assert(
1287  GNUNET_OK ==
1289  "peerinfo",
1290  "HOSTS",
1291  &networkIdDirectory));
1293  {
1295  return;
1296  }
1297 
1298  cron_scan =
1301  NULL);
1302 
1303  cron_clean =
1306  NULL);
1307  if (GNUNET_YES == use_included)
1308  {
1310  GNUNET_asprintf(&peerdir, "%shellos", ip);
1311  GNUNET_free(ip);
1312 
1314  _("Importing HELLOs from `%s'\n"),
1315  peerdir);
1316  dsc.matched = 0;
1317  dsc.remove_files = GNUNET_NO;
1318 
1321  &dsc);
1322  GNUNET_free(peerdir);
1323  }
1324  else
1325  {
1327  _("Skipping import of included HELLOs\n"));
1328  }
1329  }
1330 }
1331 
1332 
1337  "peerinfo",
1339  &run,
1342  NULL,
1343  GNUNET_MQ_hd_var_size(hello,
1345  struct GNUNET_HELLO_Message,
1346  NULL),
1349  struct ListPeerMessage,
1350  NULL),
1351  GNUNET_MQ_hd_fixed_size(get_all,
1353  struct ListAllPeersMessage,
1354  NULL),
1357  struct NotifyMessage,
1358  NULL),
1360 
1361 
1362 /* end of gnunet-service-peerinfo.c */
static void remove_garbage(const char *fullname)
Remove a file that should not be there.
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:73
#define GNUNET_MESSAGE_TYPE_PEERINFO_GET
Request update and listing of a peer.
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:51
int 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:541
int remove_files
GNUNET_YES if we should remove files that are broken, GNUNET_NO if the directory we are iterating ove...
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:662
struct GNUNET_HELLO_Message * hello
Hello for the peer (can be NULL)
Closure for add_to_tc()
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static int count_addresses(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Address iterator that counts the remaining addresses.
A HELLO message is used to exchange information about transports with other peers.
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition: nc.c:74
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static char * expiration
Credential TTL.
struct GNUNET_SERVICE_Client * client
Client to transmit to.
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.
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:89
static struct GNUNET_SCHEDULER_Task * cron_scan
Handle for task to run cron_scan_directory_data_hosts()
static void handle_hello(void *cls, const struct GNUNET_HELLO_Message *hello)
Handle HELLO-message.
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:519
static void update_hello(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello)
Bind a host address (hello) to a hostId.
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:202
Handle to a service.
Definition: service.c:114
struct GNUNET_PeerIdentity peer
Restrict to peers with this identity (optional field, check header.size!).
Definition: peerinfo.h:57
static void cron_scan_directory_data_hosts(void *cls)
Call this method periodically to scan data/hosts for new hosts.
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:1169
static void cron_clean_data_hosts(void *cls)
Call this method periodically to scan peerinfo/ for ancient HELLOs to expire.
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2424
int GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:586
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, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
static struct GNUNET_NotificationContext * notify_friend_only_list
Clients to immediately notify about all changes, even for friend-only HELLOs.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Message used to inform the client about a particular peer; this message is optionally followed by a H...
Definition: peerinfo.h:100
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:410
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:824
static int check_hello(void *cls, const struct GNUNET_HELLO_Message *hello)
Check HELLO-message.
#define GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY
Start notifying this client about all changes to the known peers until it disconnects.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:681
static int include_friend_only
Option &#39;-f&#39;.
#define DATA_HOST_CLEAN_FREQ
How often do we discard old entries in data/hosts/?
#define GNUNET_NO
Definition: gnunet_common.h:78
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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...
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *service)
Start up peerinfo service.
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.
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:909
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
int friend_only
Include friend only HELLOs GNUNET_YES or GNUNET_NO.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
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_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
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).
Handle for the service.
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:158
uint64_t abs_value_us
The actual value.
ssize_t GNUNET_DISK_fn_write(const char *fn, const void *buffer, size_t n, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file.
Definition: disk.c:877
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_PeerIdentity peer
About which peer are we talking here?
Definition: peerinfo.h:114
unsigned int matched
Counter for the number of (valid) entries found, incremented by one for each match.
Handle to a client that is connected to a service.
Definition: service.c:246
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#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
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:1237
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
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:1191
static char * value
Value of the record to add/remove.
static struct GNUNET_NotificationContext * notify_list
Clients to immediately notify about all changes.
static int discard_hosts_helper(void *cls, const char *fn)
delete expired HELLO entries in directory
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:252
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
static char * fn
Filename of the unique file.
#define DIR_SEPARATOR_STR
Definition: platform.h:168
static struct GNUNET_PEERINFO_NotifyContext * notify
Handle to the peerinfo notify service (NULL until we&#39;ve connected to it).
static void shutdown_task(void *cls)
Clean up our state.
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, the current running apps installation directory.
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 char * filename
const char * transport_name
Name of the transport plugin enabling the communication using this address.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Client connect callback.
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the &#39;monitor&#39; flag on this client.
Definition: service.c:2394
Closure for hosts_directory_scan_callback().
Internal representation of the hash map.
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_PEERINFO_INFO.
Definition: peerinfo.h:104
static int res
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
Run when otherwise idle.
static int add_to_tc(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Do transmit info about peer to given host.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
#define DIR_SEPARATOR
Definition: platform.h:167
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
static struct GNUNET_STATISTICS_Handle * stats
Handle for reporting statistics.
common internal definitions for peerinfo service
int GNUNET_HELLO_is_friend_only(const struct GNUNET_HELLO_Message *h)
Return HELLO type.
Definition: hello.c:87
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct GNUNET_CONTAINER_MultiPeerMap * hostmap
The in-memory list of known hosts, mapping of host IDs to &#39;struct HostEntry*&#39; values.
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.
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO
Information about one of the peers.
struct GNUNET_HELLO_Message * friend_only_hello
Friend only hello for the peer (can be NULL)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
int 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:254
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:119
Handle to a message queue.
Definition: mq.c:84
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.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
int 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:501
Everybody can read.
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:187
The identity of the host (wraps the signing key of the peer).
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to &#39;struct&#39;s...
configuration data
Definition: configuration.c:83
#define DATA_HOST_FREQ
How often do we scan the HOST_DIR for new entries?
Result of reading a file.
An address for communicating with a peer.
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.
static char * networkIdDirectory
Directory where the hellos are stored in (peerinfo/)
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:131
Message requesting a listing of all peers, restricted to the specified peer identity.
Definition: peerinfo.h:64
uint16_t GNUNET_HELLO_size(const struct GNUNET_HELLO_Message *hello)
Return the size of the given HELLO message.
Definition: hello.c:643
static void handle_notify(void *cls, const struct NotifyMessage *nm)
Handle NOTIFY-message.
Message requesting a listing of peers, restricted to the specified peer identity. ...
Definition: peerinfo.h:42
int 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.
static void notify_all(struct HostEntry *entry)
Broadcast information about the given entry to all clients that care.
In-memory cache of known hosts.
#define GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL
Request update and listing of all peers.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:135
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Client disconnect callback.
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.
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:351
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.
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END
End of information about other peers.
#define GNUNET_MESSAGE_TYPE_HELLO
HELLO message with friend only flag used for communicating peer addresses.
static int hosts_directory_scan_callback(void *cls, const char *fullname)
Function that is called on each HELLO file in a particular directory.
int 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".
struct GNUNET_HELLO_Message * hello
Hello for the peer (can be NULL)
static char * address
GNS address for this phone.
struct GNUNET_PeerIdentity identity
Identity of the peer.
static void handle_get_all(void *cls, const struct ListAllPeersMessage *lapm)
Handle GET-ALL-message.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
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.
static int free_host_entry(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Release memory taken by a host entry.
struct GNUNET_HELLO_Message * friend_only_hello
Friend only hello for the peer (can be NULL)
#define GNUNET_malloc(size)
Wrapper around malloc.
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:791
static void handle_get(void *cls, const struct ListPeerMessage *lpm)
Handle GET-message.
Return the directory where data is installed (share/gnunet/)
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
#define gettext_noop(String)
Definition: gettext.h:69
static struct GNUNET_SCHEDULER_Task * cron_clean
Handle for task to run cron_clean_data_hosts()
Header for all communications.
Definition: peerinfo.h:80
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956