GNUnet 0.28.1-dev.4-24-g0cf3356dd
 
Loading...
Searching...
No Matches
gnunet-service-peerstore.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014, 2015, 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
26#include "platform.h"
28#include "gnunet_protocols.h"
29#include "gnunet_util_lib.h"
30#include "peerstore.h"
32#include "peerstore_common.h"
34
35
39#define EXPIRED_RECORDS_CLEANUP_INTERVAL 300 /* 5mins */
40
47#define MAX_RECORDS_PER_ROUND 256
48
49
53struct PeerstoreClient;
54
58struct Monitor
59{
63 struct Monitor *next;
64
68 struct Monitor *prev;
69
74
79
84
89
97 uint64_t seq;
98
103 uint64_t limit;
104
112
117
122
127
132
136 char *key;
137};
138
143{
148
153
158
166 uint64_t seq;
167
171 uint32_t request_id;
172
180 uint32_t offset;
181
188
193
198
202 char *key;
203
208};
209
214{
219
224
230
236};
237
238
240{
245
249 uint32_t rid;
250
255};
256
260static const struct GNUNET_CONFIGURATION_Handle *cfg;
261
265static char *db_lib_name;
266
271
276
280static struct Monitor *monitors_head;
281
285static struct Monitor *monitors_tail;
286
291
297static void
298shutdown_task (void *cls)
299{
300 struct Monitor *mc;
301
303 "Shutting down peerstore, bye.\n");
304 /* Stop everything that could still touch the database plugin BEFORE
305 unloading it. */
306 if (NULL != expire_task)
307 {
309 expire_task = NULL;
310 }
311 while (NULL != (mc = monitors_head))
312 {
315 mc);
316 if (NULL != mc->task)
317 {
319 mc->task = NULL;
320 }
321 if (NULL != mc->sa_wait_warning)
322 {
323 GNUNET_SCHEDULER_cancel (mc->sa_wait_warning);
324 mc->sa_wait_warning = NULL;
325 }
326 GNUNET_free (mc->sub_system);
327 GNUNET_free (mc->key);
328 GNUNET_free (mc);
329 }
330 if (NULL != monitor_nc)
331 {
333 monitor_nc = NULL;
334 }
335 if (NULL != db_lib_name)
336 {
337 GNUNET_break (NULL ==
339 db));
341 db_lib_name = NULL;
342 }
343 /* NOTE: with GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN clients may still be
344 connected and sending requests at this point, so every handler that
345 uses @e db MUST check it for NULL. */
346 db = NULL;
347}
348
349
350/* Forward declaration */
351static void
352expire_records_continuation (void *cls, int success);
353
354
358static void
379
380
387static void
388expire_records_continuation (void *cls, int success)
389{
390 if (success > 0)
391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%d records expired.\n", success);
392 GNUNET_assert (NULL == expire_task);
397 NULL);
398}
399
400
406static void
408{
409 struct GNUNET_MQ_Envelope *env;
410 struct GNUNET_MessageHeader *sync;
412 "Syncing zone monitor %p\n", mc);
413
415 GNUNET_MQ_send (mc->pc->mq, env);
416 /* mark iteration done */
417 mc->in_first_iteration = GNUNET_NO;
418 mc->iteration_cnt = 0;
419}
420
421
427static void
429{
430 struct GNUNET_MQ_Envelope *env;
431 struct Monitor *mc;
432
433 // FIXME this is very inefficient, we may want to use a hash
434 // map again.
435 for (mc = monitors_head; NULL != mc; mc = mc->next)
436 {
437 if ((GNUNET_YES == mc->peer_set) &&
438 (0 != memcmp (&mc->peer, &record->peer, sizeof (record->peer))))
439 continue;
440 if ((NULL != mc->sub_system) &&
441 (0 != strcmp (mc->sub_system, record->sub_system)))
442 continue;
443 if ((NULL != mc->key) &&
444 (0 != strcmp (mc->key, record->key)))
445 continue;
446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found watcher %p to update.\n", mc);
447 if (0 == mc->limit)
448 {
450 "Watcher %p reached its limit, skipping.\n", mc);
451 continue;
452 }
454 0,
455 record->sub_system,
456 &record->peer,
457 record->key,
458 record->value,
459 record->value_size,
460 record->expiry,
461 0,
463 GNUNET_MQ_send (mc->pc->mq, env);
464 mc->limit--;
465 }
466}
467
468
474{
478 struct Iteration *ic;
479
483 uint64_t limit;
484
485};
486
497static void
498iterate_proc (void *cls,
499 uint64_t seq,
500 const struct GNUNET_PEERSTORE_Record *record,
501 const char *emsg)
502{
503 struct IterationProcResult *proc = cls;
504 struct GNUNET_MQ_Envelope *env;
505
506 if (NULL != emsg)
507 {
509 "Error iterating over peerstore: `%s'", emsg);
510 return;
511 }
512 if (NULL == record)
513 {
514 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
515 return;
516 }
517 if (0 == proc->limit)
518 {
519 /* what is this!? should never happen */
520 GNUNET_break (0);
521 return;
522 }
523 proc->ic->seq = seq;
525 proc->ic->request_id,
526 record->sub_system,
527 &record->peer,
528 record->key,
529 record->value,
530 record->value_size,
531 record->expiry,
532 0,
534 GNUNET_MQ_send (proc->ic->pc->mq, env);
535 proc->limit--;
536}
537
538
539static void
541{
542 GNUNET_free (ic->key);
544 GNUNET_free (ic);
545}
546
547
554static void
556{
557 struct GNUNET_MQ_Envelope *env;
558 struct PeerstoreResultMessage *endmsg;
559
561 if (! ic->send_end)
562 return;
563 /* No more records */
564
566 endmsg->rid = htonl (ic->request_id);
567 endmsg->result = htonl (GNUNET_OK);
568 GNUNET_MQ_send (ic->pc->mq, env);
571 return;
572}
573
574
581static void
582run_iteration_round (struct Iteration *ic, uint64_t limit)
583{
584 struct IterationProcResult proc;
587
588 if (NULL == db)
589 {
590 /* post-shutdown, see #shutdown_task() */
592 return;
593 }
594 memset (&proc, 0, sizeof(proc));
596 "Asked to return up to %llu records at position %llu\n",
597 (unsigned long long) limit,
598 (unsigned long long) ic->seq);
599 proc.ic = ic;
600 proc.limit = limit;
604 ic->sub_system,
605 (GNUNET_YES == ic->peer_set) ? &ic->peer :
606 NULL,
607 ic->key,
608 ic->seq,
609 proc.limit,
611 &proc));
614 "Returned %llu records in %s\n",
615 (unsigned long long) (limit - proc.limit),
617 if (0 == proc.limit)
619 "Returned %llu results, more results available\n",
620 (unsigned long long) limit);
621 ic->send_end = (0 != proc.limit);
623}
624
625
633static int
634check_iterate_start (void *cls, const struct
636{
637 const char *ptr = (const char *) &srm[1];
638 uint16_t ss_size;
639 uint16_t key_size;
640 uint16_t size;
641
642 ss_size = ntohs (srm->sub_system_size);
643 key_size = ntohs (srm->key_size);
644 size = ntohs (srm->header.size);
645
646 if (size < key_size + ss_size + sizeof(*srm))
647 {
648 GNUNET_break (0);
649 return GNUNET_SYSERR;
650 }
651 /* the handler GNUNET_strdup()s these, so they MUST be 0-terminated
652 within the space they claim */
653 if ((0 != ss_size) && ('\0' != ptr[ss_size - 1]))
654 {
655 GNUNET_break (0);
656 return GNUNET_SYSERR;
657 }
658 if ((0 != key_size) && ('\0' != ptr[ss_size + key_size - 1]))
659 {
660 GNUNET_break (0);
661 return GNUNET_SYSERR;
662 }
663 return GNUNET_OK;
664}
665
666
673static void
675 srm)
676{
677 struct Iteration *ic = GNUNET_new (struct Iteration);
678 uint16_t ss_size;
679 char *ptr;
680
681 ss_size = ntohs (srm->sub_system_size);
682
683 ic->pc = cls;
684 ic->request_id = ntohl (srm->rid);
685 ic->offset = 0;
686 ic->peer_set = (ntohs (srm->peer_set)) ? GNUNET_YES : GNUNET_NO;
687 if (GNUNET_YES == ic->peer_set)
688 ic->peer = srm->peer;
689 ptr = (char*) &srm[1];
690 if (0 < ss_size)
691 ic->sub_system = GNUNET_strdup (ptr);
692 ptr += ss_size;
693 if (0 < ntohs (srm->key_size))
694 ic->key = GNUNET_strdup (ptr);
696 "Iterate request: ss `%s', peer `%s', key `%s'\n",
697 ic->sub_system,
698 GNUNET_i2s (&ic->peer),
699 (NULL == ic->key) ? "NULL" : ic->key);
701 ic->pc->op_tail,
702 ic);
703 run_iteration_round (ic, 1);
704}
705
706
713static void
715 const struct PeerstoreIterationStopMessage *zis_msg)
716{
717 struct PeerstoreClient *pc = cls;
718 struct Iteration *ic;
719 uint32_t rid;
720
722 "Received ITERATION_STOP message\n");
723 /* uint32_t, and #handle_iterate_start()/#handle_iterate_next() read it
724 with ntohl(). Reading it with ntohs() here matched only rid 0, so a
725 stopped iteration was never actually found: we logged "Iteration
726 already finished" and leaked the `struct Iteration'. */
727 rid = ntohl (zis_msg->rid);
728 for (ic = pc->op_head; NULL != ic; ic = ic->next)
729 if (ic->request_id == rid)
730 break;
731 if (NULL == ic)
732 {
734 "Iteration already finished.\n");
736 return;
737 }
738 GNUNET_CONTAINER_DLL_remove (pc->op_head, pc->op_tail, ic);
741}
742
743
750static void
752 const struct PeerstoreIterationNextMessage *is_msg)
753{
754 struct PeerstoreClient *pc = cls;
755 struct Iteration *ic;
756 uint32_t rid;
757 uint64_t limit;
758
760 "Received ITERATION_NEXT message\n");
761 rid = ntohl (is_msg->rid);
762 limit = GNUNET_ntohll (is_msg->limit);
763 if (0 == limit)
764 {
765 GNUNET_break (0);
767 return;
768 }
769 if (limit > MAX_RECORDS_PER_ROUND)
770 limit = MAX_RECORDS_PER_ROUND;
771 for (ic = pc->op_head; NULL != ic; ic = ic->next)
772 if (ic->request_id == rid)
773 break;
774 if (NULL == ic)
775 {
777 "Not in iteration...\n");
778 GNUNET_break (0);
780 return;
781 }
783 "Found iteration...\n");
784 run_iteration_round (ic, limit);
785}
786
787
793static void
794monitor_iteration_next (void *cls);
795
796
807static void
809 uint64_t seq,
810 const struct GNUNET_PEERSTORE_Record *record,
811 const char *emsg)
812{
813 struct Monitor *mc = cls;
814 struct GNUNET_MQ_Envelope *env;
815
816 if (NULL != emsg)
817 {
819 "Error iterating over peerstore: `%s'", emsg);
820 return;
821 }
822 if (NULL == record)
823 {
824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
825 return;
826 }
827 GNUNET_assert (0 != seq);
828 mc->seq = seq;
829 if (0 == mc->limit)
830 {
831 /* what is this!? should never happen */
832 GNUNET_break (0);
833 return;
834 }
836 0,
837 record->sub_system,
838 &record->peer,
839 record->key,
840 record->value,
841 record->value_size,
842 record->expiry,
843 0,
845 GNUNET_MQ_send (mc->pc->mq,
846 env);
848 "Sent records.\n");
849 mc->limit--;
850 mc->iteration_cnt--;
851 if ( (0 == mc->iteration_cnt) &&
852 (0 != mc->limit) )
853 {
854 /* We are done with the current iteration batch, AND the
855 client would right now accept more, so go again! */
856 GNUNET_assert (NULL == mc->task);
858 mc);
859 }
860}
861
862
868static void
870{
871 struct Monitor *mc = cls;
872 int ret;
873
874 mc->task = NULL;
875 if (NULL == db)
876 return; /* post-shutdown, see #shutdown_task() */
877 GNUNET_assert (0 == mc->iteration_cnt);
878 if (mc->limit > 16)
879 mc->iteration_cnt = mc->limit / 2; /* leave half for monitor events */
880 else
881 mc->iteration_cnt = mc->limit; /* use it all */
882 if (mc->iteration_cnt > MAX_RECORDS_PER_ROUND)
883 mc->iteration_cnt = MAX_RECORDS_PER_ROUND;
885 "Running iteration\n");
887 mc->sub_system,
888 (GNUNET_YES == mc->peer_set) ? &mc->peer : NULL,
889 mc->key,
890 mc->seq,
891 mc->iteration_cnt,
893 mc);
894 if (GNUNET_SYSERR == ret)
895 {
896 if (NULL != mc->task)
897 {
899 mc->task = NULL;
900 }
903 mc);
904 GNUNET_free (mc->key);
905 GNUNET_free (mc->sub_system);
906 GNUNET_SERVICE_client_drop (mc->pc->client);
907 GNUNET_free (mc);
908 return;
909 }
910 if (GNUNET_NO == ret)
911 {
913 "Zone empty... syncing\n");
914 /* empty zone */
916 return;
917 }
918}
919
920
928static int
930 const struct PeerstoreMonitorStartMessage *srm)
931{
932 const char *ptr = (const char *) &srm[1];
933 uint16_t ss_size;
934 uint16_t key_size;
935 uint16_t size;
936
937 ss_size = ntohs (srm->sub_system_size);
938 key_size = ntohs (srm->key_size);
939 size = ntohs (srm->header.size);
940 if (size < key_size + ss_size + sizeof(*srm))
941 {
942 GNUNET_break (0);
943 return GNUNET_SYSERR;
944 }
945 /* the handler GNUNET_strdup()s these, so they MUST be 0-terminated
946 within the space they claim */
947 if ((0 != ss_size) && ('\0' != ptr[ss_size - 1]))
948 {
949 GNUNET_break (0);
950 return GNUNET_SYSERR;
951 }
952 if ((0 != key_size) && ('\0' != ptr[ss_size + key_size - 1]))
953 {
954 GNUNET_break (0);
955 return GNUNET_SYSERR;
956 }
957 return GNUNET_OK;
958}
959
960
967static void
969 const struct PeerstoreMonitorStartMessage *msm)
970{
971 struct PeerstoreClient *pc = cls;
972 struct Monitor *mc;
973 uint16_t ss_size;
974 char *ptr;
975
976 if (NULL == monitor_nc)
977 {
978 GNUNET_break (0);
980 return; /* post-shutdown */
981 }
982 /* The MONITOR_NEXT message carries no request ID, so #handle_monitor_next()
983 can only ever address the first monitor of a client; refuse to create a
984 second one rather than silently mis-crediting it. */
985 for (mc = monitors_head; NULL != mc; mc = mc->next)
986 if (mc->pc == pc)
987 {
988 GNUNET_break (0);
990 return;
991 }
992 mc = GNUNET_new (struct Monitor);
993 ss_size = ntohs (msm->sub_system_size);
994 mc->pc = cls;
995 mc->peer_set = (ntohs (msm->peer_set)) ? GNUNET_YES : GNUNET_NO;
996 if (GNUNET_YES == mc->peer_set)
997 mc->peer = msm->peer;
998 ptr = (char*) &msm[1];
999 if (0 < ss_size)
1000 mc->sub_system = GNUNET_strdup (ptr);
1001 ptr += ss_size;
1002 if (0 < ntohs (msm->key_size))
1003 mc->key = GNUNET_strdup (ptr);
1005 "Monitor request: ss `%s', peer `%s', key `%s'\n",
1006 mc->sub_system,
1007 GNUNET_i2s (&mc->peer),
1008 (NULL == mc->key) ? "NULL" : mc->key);
1009 mc->in_first_iteration = (GNUNET_YES == ntohs (msm->iterate_first));
1010 mc->limit = 1;
1011 mc->peer_set = (ntohs (msm->peer_set)) ? GNUNET_YES : GNUNET_NO;
1014 mc);
1016 GNUNET_SERVICE_client_continue (mc->pc->client);
1018 mc->pc->mq);
1019 if (mc->in_first_iteration)
1021 mc);
1022 else
1023 monitor_sync (mc);
1024}
1025
1026
1033static void
1035 const struct PeerstoreMonitorNextMessage *nm)
1036{
1037 struct PeerstoreClient *pc = cls;
1038 struct Monitor *mc;
1039 uint64_t inc;
1040
1041 inc = GNUNET_ntohll (nm->limit);
1042 if (inc > MAX_RECORDS_PER_ROUND)
1045 "Received MONITOR_NEXT message with limit %llu\n",
1046 (unsigned long long) inc);
1047 for (mc = monitors_head; NULL != mc; mc = mc->next)
1048 if (mc->pc == pc)
1049 break;
1050 if (NULL == mc)
1051 {
1052 GNUNET_break (0);
1054 return;
1055 }
1057 if (mc->limit + inc < mc->limit)
1058 {
1059 GNUNET_break (0);
1061 return;
1062 }
1063 mc->limit += inc;
1064 if ((mc->in_first_iteration) && (mc->limit == inc))
1065 {
1066 /* We are still iterating, and the previous iteration must
1067 have stopped due to the client's limit, so continue it! */
1068 GNUNET_assert (NULL == mc->task);
1070 }
1071 GNUNET_assert (mc->iteration_cnt <= mc->limit);
1072}
1073
1074
1081static void
1082store_record_continuation (void *cls, int success)
1083{
1084 struct StoreRecordContext *src = cls;
1086 struct GNUNET_MQ_Envelope *env;
1087
1089 msg->rid = src->rid;
1090 msg->result = htonl (success);
1091 GNUNET_MQ_send (src->pc->mq, env);
1092 watch_notifier (src->record);
1095 GNUNET_free (src);
1096}
1097
1098
1106static int
1107check_store (void *cls, const struct PeerstoreRecordMessage *srm)
1108{
1110
1112 if (NULL == record)
1113 {
1114 GNUNET_break (0);
1115 return GNUNET_SYSERR;
1116 }
1117 if ((NULL == record->sub_system) || (NULL == record->key))
1118 {
1119 GNUNET_break (0);
1121 return GNUNET_SYSERR;
1122 }
1124 return GNUNET_OK;
1125}
1126
1127
1134static void
1135handle_store (void *cls, const struct PeerstoreRecordMessage *srm)
1136{
1137 struct PeerstoreClient *pc = cls;
1138 struct StoreRecordContext *src;
1139
1140 if (NULL == db)
1141 {
1142 /* post-shutdown, see #shutdown_task() */
1144 return;
1145 }
1146 src = GNUNET_new (struct StoreRecordContext);
1148 GNUNET_log (
1150 "Received a store request. Sub system `%s' Peer `%s Key `%s' Options: %u.\n",
1151 src->record->sub_system,
1152 GNUNET_i2s (&src->record->peer),
1153 src->record->key,
1154 (uint32_t) ntohl (srm->options));
1155 src->rid = srm->rid;
1156 src->pc = pc;
1157 if (GNUNET_OK != db->store_record (db->cls,
1158 src->record->sub_system,
1159 &src->record->peer,
1160 src->record->key,
1161 src->record->value,
1162 src->record->value_size,
1163 src->record->expiry,
1164 ntohl (srm->options),
1166 src))
1167 {
1168 GNUNET_break (0);
1170 GNUNET_free (src);
1172 return;
1173 }
1174}
1175
1176
1185static void *
1187 struct GNUNET_SERVICE_Client *client,
1188 struct GNUNET_MQ_Handle *mq)
1189{
1190 struct PeerstoreClient *pc;
1191
1193 "A client %p connected\n", client);
1194 pc = GNUNET_new (struct PeerstoreClient);
1195 pc->client = client;
1196 pc->mq = mq;
1197 return pc;
1198}
1199
1200
1207static void
1210 void *app_cls)
1211{
1212 struct PeerstoreClient *pc = app_cls;
1213 struct Iteration *iter;
1214 struct Monitor *mo;
1215
1216 (void) cls;
1218 "Client %p disconnected.\n",
1219 client);
1220 for (mo = monitors_head; NULL != mo; mo = mo->next)
1221 {
1222 if (pc != mo->pc)
1223 continue;
1226 mo);
1227 if (NULL != mo->task)
1228 {
1230 mo->task = NULL;
1231 }
1232 if (NULL != mo->sa_wait_warning)
1233 {
1235 mo->sa_wait_warning = NULL;
1236 }
1237 GNUNET_free (mo->sub_system);
1238 GNUNET_free (mo->key);
1239 GNUNET_free (mo);
1240 // Restart from monitors_head
1241 mo = monitors_head;
1242 }
1243 while (NULL != (iter = pc->op_head))
1244 {
1246 pc->op_tail,
1247 iter);
1248 destroy_iteration (iter);
1249 }
1250 GNUNET_free (pc);
1251}
1252
1253
1254static void
1255store_hello_continuation (void *cls, int success)
1256{
1257 (void) cls;
1258
1259 if (GNUNET_OK != success)
1260 {
1262 "Error storing bootstrap hello!\n");
1263 GNUNET_break (0);
1264 }
1265}
1266
1267
1268static int
1269hosts_directory_scan_callback (void *cls, const char *fullname)
1270{
1271 ssize_t size_total;
1272 char buffer[GNUNET_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
1273 const struct GNUNET_MessageHeader *hello;
1274 struct GNUNET_MQ_Envelope *env;
1275 struct GNUNET_HELLO_Parser *parser;
1276 const struct GNUNET_PeerIdentity *pid;
1277 struct GNUNET_TIME_Absolute et;
1278 (void) cls;
1279
1280 if (GNUNET_YES != GNUNET_DISK_file_test (fullname))
1281 return GNUNET_OK; /* ignore non-files */
1282
1283 size_total = GNUNET_DISK_fn_read (fullname, buffer, sizeof(buffer) - 1);
1285 "Read %d bytes from `%s'\n",
1286 (int) size_total,
1287 fullname);
1288 if ((size_total < 0) ||
1289 (((size_t) size_total) < sizeof(struct GNUNET_MessageHeader)))
1290 {
1292 _ ("Failed to parse HELLO in file `%s': %s\n"),
1293 fullname,
1294 "File has invalid size");
1295 return GNUNET_OK;
1296 }
1297 buffer[size_total] = '\0';
1298 parser = GNUNET_HELLO_parser_from_url (buffer);
1299 if (NULL == parser)
1300 {
1302 "Unable to parse HELLO url\n");
1303 return GNUNET_OK;
1304 }
1306 hello = GNUNET_MQ_env_get_msg (env);
1307 pid = GNUNET_HELLO_parser_get_id (parser);
1310 "store contrib hello for peer %s\n",
1311 GNUNET_i2s (pid));
1312
1313 if (GNUNET_OK != db->store_record (db->cls,
1314 "peerstore",
1315 pid,
1317 hello,
1318 ntohs (hello->size),
1319 et,
1322 NULL))
1323 {
1324 GNUNET_break (0);
1325 }
1327 GNUNET_HELLO_parser_free (parser);
1328 return GNUNET_OK;
1329}
1330
1331
1339static void
1340run (void *cls,
1341 const struct GNUNET_CONFIGURATION_Handle *c,
1343{
1344 char *database;
1345 int use_included;
1346 char *ip;
1347 char *peerdir;
1348
1349 cfg = c;
1350
1351 if (GNUNET_OK !=
1353 "peerstore",
1354 "DATABASE",
1355 &database))
1356 {
1358 "peerstore",
1359 "DATABASE");
1361 return;
1362 }
1364 "libgnunet_plugin_peerstore_%s",
1365 database);
1368 (void *) cfg);
1369 GNUNET_free (database);
1370 if (NULL == db)
1371 {
1373 _ ("Could not load database backend `%s'\n"),
1374 db_lib_name);
1376 return;
1377 }
1379 NULL);
1381 "peerstore",
1382 "USE_INCLUDED_HELLOS");
1383 if (GNUNET_SYSERR == use_included)
1384 use_included = GNUNET_NO;
1385 if (GNUNET_YES == use_included)
1386 {
1389 GNUNET_asprintf (&peerdir, "%shellos", ip);
1390 GNUNET_free (ip);
1391
1393 _ ("Importing HELLOs from `%s'\n"),
1394 peerdir);
1397 NULL);
1398 GNUNET_free (peerdir);
1399 }
1400 else
1401 {
1403 _ ("Skipping import of included HELLOs\n"));
1404 }
1407 NULL);
1408}
1409
1410
1417 &client_disconnect_cb, NULL,
1419 struct PeerstoreRecordMessage, NULL),
1420 GNUNET_MQ_hd_var_size (iterate_start,
1422 struct PeerstoreIterationStartMessage, NULL),
1423 GNUNET_MQ_hd_fixed_size (iterate_stop,
1425 struct PeerstoreIterationStopMessage, NULL),
1426 GNUNET_MQ_hd_fixed_size (iterate_next,
1429 NULL),
1430 GNUNET_MQ_hd_var_size (monitor_start,
1433 NULL),
1434 GNUNET_MQ_hd_fixed_size (monitor_next,
1437 NULL),
1439
1440
1441/* end of gnunet-service-peerstore.c */
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
struct GNUNET_SCHEDULER_Task * shutdown_task
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
static struct GNUNET_TESTBED_Controller * mc
Handle to the master controller.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static void watch_notifier(struct GNUNET_PEERSTORE_Record *record)
Given a new record, notifies watchers.
static void handle_iterate_next(void *cls, const struct PeerstoreIterationNextMessage *is_msg)
Handles a #GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATION_NEXT message.
static void handle_monitor_start(void *cls, const struct PeerstoreMonitorStartMessage *msm)
Handle an iterate request from client.
static void run_iteration_round(struct Iteration *ic, uint64_t limit)
Perform the next round of the zone iteration.
static void handle_iterate_start(void *cls, const struct PeerstoreIterationStartMessage *srm)
Handle an iterate request from client.
static void destroy_iteration(struct Iteration *ic)
static void handle_monitor_next(void *cls, const struct PeerstoreMonitorNextMessage *nm)
Handles a GNUNET_MESSAGE_TYPE_PEERSTORE_MONITOR_NEXT message.
static int hosts_directory_scan_callback(void *cls, const char *fullname)
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static struct GNUNET_NotificationContext * monitor_nc
Notification context shared by all monitors.
static struct Monitor * monitors_head
Monitor DLL.
static int check_monitor_start(void *cls, const struct PeerstoreMonitorStartMessage *srm)
Check a monitor request from client.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_cls)
A client disconnected.
static char * db_lib_name
Database plugin library name.
static void expire_records_continuation(void *cls, int success)
Continuation to expire_records called by the peerstore plugin.
static void iterate_proc(void *cls, uint64_t seq, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Process results for zone iteration from database.
#define EXPIRED_RECORDS_CLEANUP_INTERVAL
Interval for expired records cleanup (in seconds)
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client disconnected.
static int check_store(void *cls, const struct PeerstoreRecordMessage *srm)
Check a store request from client.
static void store_record_continuation(void *cls, int success)
Continuation of store_record called by the peerstore plugin.
static void monitor_sync(struct Monitor *mc)
Send 'sync' message to zone monitor, we're now in sync.
static struct GNUNET_PEERSTORE_PluginFunctions * db
Database handle.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Peerstore service runner.
static void monitor_iterate_cb(void *cls, uint64_t seq, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
A GNUNET_NAMESTORE_RecordIterator for monitors.
static void store_hello_continuation(void *cls, int success)
static struct GNUNET_SCHEDULER_Task * expire_task
Task run to clean up expired records.
static void cleanup_expired_records(void *cls)
Deletes any expired records from storage.
static void monitor_iteration_next(void *cls)
Obtain the next datum during the monitor's initial iteration.
static int check_iterate_start(void *cls, const struct PeerstoreIterationStartMessage *srm)
Check an iterate request from client.
static void handle_iterate_stop(void *cls, const struct PeerstoreIterationStopMessage *zis_msg)
Handles a #GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATION_STOP message.
#define MAX_RECORDS_PER_ROUND
Maximum number of records we hand out in a single iteration round, regardless of what the client aske...
static void handle_store(void *cls, const struct PeerstoreRecordMessage *srm)
Handle a store request from client.
static struct Monitor * monitors_tail
Monitor DLL.
static void iteration_done_client_continue(struct Iteration *ic)
Function called once we are done with the iteration and allow the zone iteration client to send us mo...
static struct GNUNET_TIME_Relative duration
Option '-d': duration of the mapping.
Definition gnunet-vpn.c:90
Helper library for handling HELLO URIs.
Plugin API for the peerstore database backend.
API to the peerstore service.
Constants for network protocols.
#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_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_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
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:557
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:720
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition disk.c:881
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c:380
struct GNUNET_MQ_Envelope * GNUNET_HELLO_parser_to_env(const struct GNUNET_HELLO_Parser *parser)
Generate envelope with GNUnet HELLO message (including peer ID) from a parser.
Definition hello-uri.c:967
struct GNUNET_TIME_Absolute GNUNET_HELLO_get_expiration_time_from_msg(const struct GNUNET_MessageHeader *msg)
Get the expiration time for this HELLO.
Definition hello-uri.c:642
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_get_id(const struct GNUNET_HELLO_Parser *parser)
Get the PeerIdentity for this builder.
Definition hello-uri.c:354
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_url(const char *url)
Parse GNUnet HELLO url.
Definition hello-uri.c:727
#define GNUNET_log(kind,...)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
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.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ 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_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#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:138
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:337
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition mq.c:317
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition nc.c:122
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition mq.c:928
#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:161
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
char * GNUNET_OS_installation_get_path(const struct GNUNET_OS_ProjectData *pd, 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_PEERSTORE_HELLO_KEY
Key used for storing HELLO in the peerstore.
@ GNUNET_PEERSTORE_STOREOPTION_MULTIPLE
Possibly store multiple values under given key.
void * GNUNET_PLUGIN_load(const struct GNUNET_OS_ProjectData *pd, const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition plugin.c:221
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition plugin.c:277
#define GNUNET_MESSAGE_TYPE_PEERSTORE_MONITOR_SYNC
Monitor sync.
#define GNUNET_MESSAGE_TYPE_PEERSTORE_STORE
Store request message.
#define GNUNET_MESSAGE_TYPE_PEERSTORE_MONITOR_NEXT
Monitor next request.
#define GNUNET_MESSAGE_TYPE_PEERSTORE_MONITOR_START
Monitor request.
#define GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_START
Iteration request (see also 828, 829)
#define GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_NEXT
Iteration request (see also 821, 829)
#define GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_STOP
Iteration request (see also 821, 828)
#define GNUNET_MESSAGE_TYPE_PEERSTORE_RECORD
Record result message.
#define GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END
Iteration end message.
#define GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT
Store result message.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
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:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
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:1283
#define GNUNET_SERVICE_MAIN(pd, service_name, service_options, init_cb, connect_cb, disconnect_cb, cls,...)
Creates the "main" function for a GNUnet service.
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition service.c:2528
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2463
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2434
@ GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition time.c:438
#define GNUNET_TIME_UNIT_SECONDS
One second.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:610
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486
static unsigned int size
Size of the "table".
Definition peer.c:68
IPC messages.
struct GNUNET_PEERSTORE_Record * PEERSTORE_parse_record_message(const struct PeerstoreRecordMessage *srm)
Parses a message carrying a record.
struct GNUNET_MQ_Envelope * PEERSTORE_create_record_mq_envelope(uint32_t rid, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t value_size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, uint16_t msg_type)
Creates a MQ envelope for a single record.
void PEERSTORE_destroy_record(struct GNUNET_PEERSTORE_Record *record)
Free any memory allocated for this record.
Helper peerstore functions.
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
struct GNUNET_MQ_Handle * mq
Our own message queue for the FS service; only briefly used when we start to index a file,...
Definition fs_api.h:1234
Context for parsing HELLOs.
Definition hello-uri.c:233
Handle to a message queue.
Definition mq.c:87
Header for all communications.
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition nc.c:77
struct returned by the initialization function of the plugin
void * cls
Closure to pass to all plugin functions.
int(* iterate_records)(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, uint64_t serial, uint64_t limit, GNUNET_PEERSTORE_PluginProcessor iter, void *iter_cls)
Iterate over the records given an optional peer id and/or key.
int(* store_record)(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a record in the peerstore.
int(* expire_records)(void *cls, struct GNUNET_TIME_Absolute now, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Delete expired records (expiry < now)
size_t value_size
Size of value BLOB.
struct GNUNET_PeerIdentity peer
Peer Identity.
void * value
Record value BLOB.
struct GNUNET_TIME_Absolute expiry
Expiry time of entry.
char * sub_system
Responsible sub system string.
char * key
Record key string.
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition scheduler.c:141
Handle to a client that is connected to a service.
Definition service.c:249
Handle to a service.
Definition service.c:116
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
Context for iteration operations passed from run_iteration_round to iterate_proc as closure.
struct Iteration * ic
The zone iteration handle.
uint64_t limit
Number of results left to be returned in this iteration.
A peerstore iteration operation.
int send_end
Set to GNUNET_YES if the last iteration exhausted the limit set by the client and we should send the ...
uint64_t seq
Last sequence number in the zone iteration used to address next result of the zone iteration in the s...
char * sub_system
Responsible sub system string.
char * key
Record key string.
struct GNUNET_PeerIdentity peer
Peer Identity.
struct PeerstoreClient * pc
Namestore client which initiated this zone iteration.
struct Iteration * prev
Previous element in the DLL.
int peer_set
Peer is set?
uint32_t offset
Offset of the zone iteration used to address next result of the zone iteration in the store.
uint32_t request_id
The operation id for the zone iteration in the response for the client.
struct Iteration * next
Next element in the DLL.
A peerstore monitor.
struct PeerstoreClient * pc
Namestore client which initiated this zone monitor.
struct Monitor * next
Next element in the DLL.
uint64_t limit
Current limit of how many more messages we are allowed to queue to this monitor.
struct GNUNET_PeerIdentity peer
Peer Identity.
uint64_t seq
Last sequence number in the zone iteration used to address next result of the iteration in the store.
struct GNUNET_SCHEDULER_Task * task
Task active during initial iteration.
char * key
Record key string.
int in_first_iteration
Are we (still) in the initial iteration pass?
struct Monitor * prev
Previous element in the DLL.
char * sub_system
Responsible sub system string.
struct GNUNET_TIME_Absolute sa_waiting_start
Since when are we blocked on this monitor?
uint64_t iteration_cnt
How many more requests may we receive from the iterator before it is at the limit we gave it?...
struct GNUNET_SCHEDULER_Task * sa_wait_warning
Task to warn about slow monitors.
int peer_set
Is the peer set?
A peerstore client.
struct Iteration * op_head
Head of the DLL of Zone iteration operations in progress initiated by this client.
struct GNUNET_MQ_Handle * mq
Message queue for transmission to client.
struct GNUNET_SERVICE_Client * client
The client.
struct Iteration * op_tail
Tail of the DLL of Zone iteration operations in progress initiated by this client.
Iteration next message.
Definition peerstore.h:248
uint32_t rid
Request id.
Definition peerstore.h:262
uint64_t limit
Number of records to return.
Definition peerstore.h:257
Iteration start message.
Definition peerstore.h:202
struct GNUNET_MessageHeader header
GNUnet message header.
Definition peerstore.h:206
uint16_t peer_set
GNUNET_YES if peer id value set, GNUNET_NO otherwise
Definition peerstore.h:221
struct GNUNET_PeerIdentity peer
Peer Identity.
Definition peerstore.h:211
uint32_t rid
Request id.
Definition peerstore.h:216
uint16_t sub_system_size
Size of the sub_system string Allocated at position 0 after this struct.
Definition peerstore.h:227
uint16_t key_size
Size of the key string Allocated at position 1 after this struct.
Definition peerstore.h:238
uint32_t rid
Request id.
Definition peerstore.h:275
Iteration next message.
Definition peerstore.h:185
uint64_t limit
Number of records to return.
Definition peerstore.h:194
Iteration start message.
Definition peerstore.h:140
uint16_t iterate_first
GNUNET_YES if iterate first, GNUNET_NO otherwise
Definition peerstore.h:176
struct GNUNET_PeerIdentity peer
Peer Identity.
Definition peerstore.h:149
uint16_t peer_set
GNUNET_YES if peer id value set, GNUNET_NO otherwise
Definition peerstore.h:165
uint16_t key_size
Size of the key string Allocated at position 1 after this struct.
Definition peerstore.h:160
uint16_t sub_system_size
Size of the sub_system string Allocated at position 0 after this struct.
Definition peerstore.h:171
struct GNUNET_MessageHeader header
GNUnet message header.
Definition peerstore.h:144
Message carrying a PEERSTORE record message.
Definition peerstore.h:38
uint32_t rid
Request id.
Definition peerstore.h:57
uint32_t options
Options, needed only in case of a store operation.
Definition peerstore.h:63
Message carrying a PEERSTORE result message.
Definition peerstore.h:96
uint32_t result
Options, needed only in case of a store operation.
Definition peerstore.h:111
uint32_t rid
Request id.
Definition peerstore.h:105
struct GNUNET_PEERSTORE_Record * record
The record that was stored.
uint32_t rid
The request ID.
struct PeerstoreClient * pc
The client.