GNUnet 0.22.2
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
41
45struct PeerstoreClient;
46
50struct Monitor
51{
55 struct Monitor *next;
56
60 struct Monitor *prev;
61
66
71
76
81
89 uint64_t seq;
90
95 uint64_t limit;
96
104
109
114
119
124
128 char *key;
129};
130
135{
140
145
150
158 uint64_t seq;
159
163 uint32_t request_id;
164
172 uint32_t offset;
173
180
185
190
194 char *key;
195
200};
201
206{
211
216
222
228};
229
230
232{
237
241 uint32_t rid;
242
247};
248
252static const struct GNUNET_CONFIGURATION_Handle *cfg;
253
257static char *db_lib_name;
258
263
268
272static struct Monitor *monitors_head;
273
277static struct Monitor *monitors_tail;
278
283
289static void
290shutdown_task (void *cls)
291{
293 "Shutting down peerstore, bye.\n");
294 if (NULL != db_lib_name)
295 {
298 db_lib_name = NULL;
299 }
300 if (NULL != expire_task)
301 {
303 expire_task = NULL;
304 }
305 if (NULL != monitor_nc)
306 {
308 monitor_nc = NULL;
309 }
310}
311
312
313/* Forward declaration */
314static void
315expire_records_continuation (void *cls, int success);
316
317
321static void
323{
324 int ret;
325
326 expire_task = NULL;
327 GNUNET_assert (NULL != db);
331 NULL);
332 if (GNUNET_OK != ret)
333 {
334 GNUNET_assert (NULL == expire_task);
339 NULL);
340 }
341}
342
343
350static void
351expire_records_continuation (void *cls, int success)
352{
353 if (success > 0)
354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%d records expired.\n", success);
355 GNUNET_assert (NULL == expire_task);
360 NULL);
361}
362
363
369static void
371{
372 struct GNUNET_MQ_Envelope *env;
373 struct GNUNET_MessageHeader *sync;
375 "Syncing zone monitor %p\n", mc);
376
378 GNUNET_MQ_send (mc->pc->mq, env);
379 /* mark iteration done */
380 mc->in_first_iteration = GNUNET_NO;
381 mc->iteration_cnt = 0;
382}
383
384
390static void
392{
393 struct GNUNET_MQ_Envelope *env;
394 struct Monitor *mc;
395
396 // FIXME this is very inefficient, we may want to use a hash
397 // map again.
398 for (mc = monitors_head; NULL != mc; mc = mc->next)
399 {
400 if ((GNUNET_YES == mc->peer_set) &&
401 (0 != memcmp (&mc->peer, &record->peer, sizeof (record->peer))))
402 continue;
403 if ((NULL != mc->sub_system) &&
404 (0 != strcmp (mc->sub_system, record->sub_system)))
405 continue;
406 if ((NULL != mc->key) &&
407 (0 != strcmp (mc->key, record->key)))
408 continue;
409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found watcher %p to update.\n", mc);
411 0,
412 record->sub_system,
413 &record->peer,
414 record->key,
415 record->value,
416 record->value_size,
417 record->expiry,
418 0,
420 GNUNET_MQ_send (mc->pc->mq, env);
421 }
422}
423
424
430{
434 struct Iteration *ic;
435
439 uint64_t limit;
440
441};
442
453static void
454iterate_proc (void *cls,
455 uint64_t seq,
456 const struct GNUNET_PEERSTORE_Record *record,
457 const char *emsg)
458{
459 struct IterationProcResult *proc = cls;
460 struct GNUNET_MQ_Envelope *env;
461
462 if (NULL != emsg)
463 {
465 "Error iterating over peerstore: `%s'", emsg);
466 return;
467 }
468 if (NULL == record)
469 {
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
471 return;
472 }
473 if (0 == proc->limit)
474 {
475 /* what is this!? should never happen */
476 GNUNET_break (0);
477 return;
478 }
479 proc->ic->seq = seq;
481 proc->ic->request_id,
482 record->sub_system,
483 &record->peer,
484 record->key,
485 record->value,
486 record->value_size,
487 record->expiry,
488 0,
490 GNUNET_MQ_send (proc->ic->pc->mq, env);
491 proc->limit--;
492}
493
494
495static void
497{
498 GNUNET_free (ic->key);
500 GNUNET_free (ic);
501}
502
503
510static void
512{
513 struct GNUNET_MQ_Envelope *env;
514 struct PeerstoreResultMessage *endmsg;
515
517 if (! ic->send_end)
518 return;
519 /* No more records */
520
522 endmsg->rid = htons (ic->request_id);
523 endmsg->result = htonl (GNUNET_OK);
524 GNUNET_MQ_send (ic->pc->mq, env);
527 return;
528}
529
530
537static void
538run_iteration_round (struct Iteration *ic, uint64_t limit)
539{
540 struct IterationProcResult proc;
543
544 memset (&proc, 0, sizeof(proc));
546 "Asked to return up to %llu records at position %llu\n",
547 (unsigned long long) limit,
548 (unsigned long long) ic->seq);
549 proc.ic = ic;
550 proc.limit = limit;
554 ic->sub_system,
555 (GNUNET_YES == ic->peer_set) ? &ic->peer :
556 NULL,
557 ic->key,
558 ic->seq,
559 proc.limit,
561 &proc));
564 if (0 == proc.limit)
566 "Returned %llu results, more results available\n",
567 (unsigned long long) limit);
568 ic->send_end = (0 != proc.limit);
570}
571
572
580static int
581check_iterate_start (void *cls, const struct
583{
584 uint16_t ss_size;
585 uint16_t key_size;
586 uint16_t size;
587
588 ss_size = ntohs (srm->sub_system_size);
589 key_size = ntohs (srm->key_size);
590 size = ntohs (srm->header.size);
591
592 if (size < key_size + ss_size + sizeof(*srm))
593 {
594 GNUNET_break (0);
595 return GNUNET_SYSERR;
596 }
597 return GNUNET_OK;
598}
599
600
607static void
609 srm)
610{
611 struct Iteration *ic = GNUNET_new (struct Iteration);
612 uint16_t ss_size;
613 char *ptr;
614
615 ss_size = ntohs (srm->sub_system_size);
616
617 ic->pc = cls;
618 ic->request_id = ntohs (srm->rid);
619 ic->offset = 0;
620 ic->peer_set = (ntohs (srm->peer_set)) ? GNUNET_YES : GNUNET_NO;
621 if (GNUNET_YES == ic->peer_set)
622 ic->peer = srm->peer;
623 ptr = (char*) &srm[1];
624 ic->sub_system = GNUNET_strdup (ptr);
625 ptr += ss_size;
626 if (0 < ntohs (srm->key_size))
627 ic->key = GNUNET_strdup (ptr);
629 "Iterate request: ss `%s', peer `%s', key `%s'\n",
630 ic->sub_system,
631 GNUNET_i2s (&ic->peer),
632 (NULL == ic->key) ? "NULL" : ic->key);
634 ic->pc->op_tail,
635 ic);
636 run_iteration_round (ic, 1);
637}
638
639
646static void
648 const struct PeerstoreIterationStopMessage *zis_msg)
649{
650 struct PeerstoreClient *pc = cls;
651 struct Iteration *ic;
652 uint32_t rid;
653
655 "Received ITERATION_STOP message\n");
656 rid = ntohs (zis_msg->rid);
657 for (ic = pc->op_head; NULL != ic; ic = ic->next)
658 if (ic->request_id == rid)
659 break;
660 if (NULL == ic)
661 {
663 "Iteration already finished.\n");
665 return;
666 }
667 GNUNET_CONTAINER_DLL_remove (pc->op_head, pc->op_tail, ic);
670}
671
672
679static void
681 const struct PeerstoreIterationNextMessage *is_msg)
682{
683 struct PeerstoreClient *pc = cls;
684 struct Iteration *ic;
685 uint32_t rid;
686 uint64_t limit;
687
689 "Received ITERATION_NEXT message\n");
690 rid = ntohs (is_msg->rid);
691 limit = GNUNET_ntohll (is_msg->limit);
692 for (ic = pc->op_head; NULL != ic; ic = ic->next)
693 if (ic->request_id == rid)
694 break;
695 if (NULL == ic)
696 {
698 "Not in iteration...\n");
699 GNUNET_break (0);
701 return;
702 }
704 "Found iteration...\n");
705 run_iteration_round (ic, limit);
706}
707
708
714static void
715monitor_iteration_next (void *cls);
716
717
728static void
730 uint64_t seq,
731 const struct GNUNET_PEERSTORE_Record *record,
732 const char *emsg)
733{
734 struct Monitor *mc = cls;
735 struct GNUNET_MQ_Envelope *env;
736
737 GNUNET_assert (0 != seq);
738 mc->seq = seq;
739
740 if (NULL != emsg)
741 {
743 "Error iterating over peerstore: `%s'", emsg);
744 return;
745 }
746 if (NULL == record)
747 {
748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
749 return;
750 }
751 if (0 == mc->limit)
752 {
753 /* what is this!? should never happen */
754 GNUNET_break (0);
755 return;
756 }
758 0,
759 record->sub_system,
760 &record->peer,
761 record->key,
762 record->value,
763 record->value_size,
764 record->expiry,
765 0,
767 GNUNET_MQ_send (mc->pc->mq, env);
768
770 "Sent records.\n");
771 mc->limit--;
772 mc->iteration_cnt--;
773 if ((0 == mc->iteration_cnt) && (0 != mc->limit))
774 {
775 /* We are done with the current iteration batch, AND the
776 client would right now accept more, so go again! */
777 GNUNET_assert (NULL == mc->task);
779 }
780}
781
782
788static void
790{
791 struct Monitor *mc = cls;
792 int ret;
793
794 mc->task = NULL;
795 GNUNET_assert (0 == mc->iteration_cnt);
796 if (mc->limit > 16)
797 mc->iteration_cnt = mc->limit / 2; /* leave half for monitor events */
798 else
799 mc->iteration_cnt = mc->limit; /* use it all */
801 "Running iteration\n");
803 mc->sub_system,
804 (GNUNET_YES == mc->peer_set) ? &mc->peer : NULL,
805 mc->key,
806 mc->seq,
807 mc->iteration_cnt,
809 mc);
810 if (GNUNET_SYSERR == ret)
811 {
812 GNUNET_free (mc->key);
813 GNUNET_free (mc->sub_system);
814 GNUNET_SERVICE_client_drop (mc->pc->client);
815 GNUNET_free (mc);
816 return;
817 }
818 if (GNUNET_NO == ret)
819 {
821 "Zone empty... syncing\n");
822 /* empty zone */
824 return;
825 }
826}
827
828
836static int
838{
839 uint16_t ss_size;
840 uint16_t key_size;
841 uint16_t size;
842
843 ss_size = ntohs (srm->sub_system_size);
844 key_size = ntohs (srm->key_size);
845 size = ntohs (srm->header.size);
846
847 if (size < key_size + ss_size + sizeof(*srm))
848 {
849 GNUNET_break (0);
850 return GNUNET_SYSERR;
851 }
852 return GNUNET_OK;
853}
854
855
862static void
864{
865 struct Monitor *mc = GNUNET_new (struct Monitor);
866
867 uint16_t ss_size;
868 char *ptr;
869
870 ss_size = ntohs (msm->sub_system_size);
871
872 mc->pc = cls;
873 mc->peer_set = (ntohs (msm->peer_set)) ? GNUNET_YES : GNUNET_NO;
874 if (GNUNET_YES == mc->peer_set)
875 mc->peer = msm->peer;
876 ptr = (char*) &msm[1];
877 if (0 < ss_size)
878 mc->sub_system = GNUNET_strdup (ptr);
879 ptr += ss_size;
880 if (0 < ntohs (msm->key_size))
881 mc->key = GNUNET_strdup (ptr);
883 "Monitor request: ss `%s', peer `%s', key `%s'\n",
884 mc->sub_system,
885 GNUNET_i2s (&mc->peer),
886 (NULL == mc->key) ? "NULL" : mc->key);
887 mc->in_first_iteration = (GNUNET_YES == ntohs (msm->iterate_first));
888 mc->limit = 1;
889 mc->peer_set = (ntohs (msm->peer_set)) ? GNUNET_YES : GNUNET_NO;
892 mc);
896 if (mc->in_first_iteration)
898 else
900}
901
902
909static void
911{
912 struct PeerstoreClient *pc = cls;
913 struct Monitor *mc;
914 uint64_t inc;
915
916 inc = GNUNET_ntohll (nm->limit);
918 "Received MONITOR_NEXT message with limit %llu\n",
919 (unsigned long long) inc);
920 for (mc = monitors_head; NULL != mc; mc = mc->next)
921 if (mc->pc == pc)
922 break;
923 if (NULL == mc)
924 {
925 GNUNET_break (0);
927 return;
928 }
930 if (mc->limit + inc < mc->limit)
931 {
932 GNUNET_break (0);
934 return;
935 }
936 mc->limit += inc;
937 if ((mc->in_first_iteration) && (mc->limit == inc))
938 {
939 /* We are still iterating, and the previous iteration must
940 have stopped due to the client's limit, so continue it! */
941 GNUNET_assert (NULL == mc->task);
943 }
944 GNUNET_assert (mc->iteration_cnt <= mc->limit);
945}
946
947
954static void
955store_record_continuation (void *cls, int success)
956{
957 struct StoreRecordContext *src = cls;
959 struct GNUNET_MQ_Envelope *env;
960
962 msg->rid = src->rid;
963 msg->result = htonl (success);
964 GNUNET_MQ_send (src->pc->mq, env);
965 watch_notifier (src->record);
968 GNUNET_free (src);
969}
970
971
979static int
980check_store (void *cls, const struct PeerstoreRecordMessage *srm)
981{
983
985 if (NULL == record)
986 {
987 GNUNET_break (0);
988 return GNUNET_SYSERR;
989 }
990 if ((NULL == record->sub_system) || (NULL == record->key))
991 {
992 GNUNET_break (0);
994 return GNUNET_SYSERR;
995 }
997 return GNUNET_OK;
998}
999
1000
1007static void
1008handle_store (void *cls, const struct PeerstoreRecordMessage *srm)
1009{
1010 struct PeerstoreClient *pc = cls;
1011 struct StoreRecordContext *src = GNUNET_new (struct StoreRecordContext);
1013 GNUNET_log (
1015 "Received a store request. Sub system `%s' Peer `%s Key `%s' Options: %u.\n",
1016 src->record->sub_system,
1017 GNUNET_i2s (&src->record->peer),
1018 src->record->key,
1019 (uint32_t) ntohl (srm->options));
1020 src->rid = srm->rid;
1021 src->pc = pc;
1022 if (GNUNET_OK != db->store_record (db->cls,
1023 src->record->sub_system,
1024 &src->record->peer,
1025 src->record->key,
1026 src->record->value,
1027 src->record->value_size,
1028 src->record->expiry,
1029 ntohl (srm->options),
1031 src))
1032 {
1033 GNUNET_break (0);
1035 GNUNET_free (src);
1037 GNUNET_free (pc);
1038 return;
1039 }
1040}
1041
1042
1051static void *
1053 struct GNUNET_SERVICE_Client *client,
1054 struct GNUNET_MQ_Handle *mq)
1055{
1056 struct PeerstoreClient *pc;
1057
1059 "A client %p connected\n", client);
1060 pc = GNUNET_new (struct PeerstoreClient);
1061 pc->client = client;
1062 pc->mq = mq;
1063 return pc;
1064}
1065
1066
1073static void
1076 void *app_cls)
1077{
1078 struct PeerstoreClient *pc = app_cls;
1079 struct Iteration *iter;
1080 struct Monitor *mo;
1081
1082 (void) cls;
1084 "Client %p disconnected.\n",
1085 client);
1086 for (mo = monitors_head; NULL != mo; mo = mo->next)
1087 {
1088 if (pc != mo->pc)
1089 continue;
1091 if (NULL != mo->task)
1092 {
1094 mo->task = NULL;
1095 }
1096 if (NULL != mo->sa_wait_warning)
1097 {
1099 mo->sa_wait_warning = NULL;
1100 }
1101 GNUNET_free (mo->sub_system);
1102 GNUNET_free (mo->key);
1103 GNUNET_free (mo);
1104 break;
1105 }
1106 while (NULL != (iter = pc->op_head))
1107 {
1108 GNUNET_CONTAINER_DLL_remove (pc->op_head, pc->op_tail, iter);
1109 destroy_iteration (iter);
1110 }
1111 GNUNET_free (pc);
1112}
1113
1114
1115static void
1116store_hello_continuation (void *cls, int success)
1117{
1118 (void) cls;
1119
1120 if (GNUNET_OK != success)
1121 {
1123 "Error storing bootstrap hello!\n");
1124 GNUNET_break (0);
1125 }
1126}
1127
1128
1129static int
1130hosts_directory_scan_callback (void *cls, const char *fullname)
1131{
1132 ssize_t size_total;
1133 char buffer[GNUNET_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
1134 const struct GNUNET_MessageHeader *hello;
1136 const struct GNUNET_PeerIdentity *pid;
1137 struct GNUNET_TIME_Absolute et;
1138 (void) cls;
1139
1140 if (GNUNET_YES != GNUNET_DISK_file_test (fullname))
1141 return GNUNET_OK; /* ignore non-files */
1142
1143 size_total = GNUNET_DISK_fn_read (fullname, buffer, sizeof(buffer));
1145 "Read %d bytes from `%s'\n",
1146 (int) size_total,
1147 fullname);
1148 if ((size_total < 0) ||
1149 (((size_t) size_total) < sizeof(struct GNUNET_MessageHeader)))
1150 {
1152 _ ("Failed to parse HELLO in file `%s': %s\n"),
1153 fullname,
1154 "File has invalid size");
1155 return GNUNET_OK;
1156 }
1157 hello = (const struct GNUNET_MessageHeader *) &buffer[0];
1159 if (NULL == parser)
1160 {
1162 "Unable to parse HELLO message\n");
1163 return GNUNET_OK;
1164 }
1168 "store contrib hello for peer %s\n",
1169 GNUNET_i2s (pid));
1170
1171 if (GNUNET_OK != db->store_record (db->cls,
1172 "peerstore",
1173 pid,
1175 hello,
1176 size_total,
1177 et,
1180 NULL))
1181 {
1182 GNUNET_break (0);
1183 }
1185 return GNUNET_OK;
1186}
1187
1188
1196static void
1197run (void *cls,
1198 const struct GNUNET_CONFIGURATION_Handle *c,
1200{
1201 char *database;
1202 int use_included;
1203 char *ip;
1204 char *peerdir;
1205
1206 cfg = c;
1207
1209 "peerstore",
1210 "DATABASE",
1211 &database))
1212 {
1214 "peerstore",
1215 "DATABASE");
1217 return;
1218 }
1220 "libgnunet_plugin_peerstore_%s",
1221 database);
1224 (void *) cfg);
1225 GNUNET_free (database);
1226 if (NULL == db)
1227 {
1229 _ ("Could not load database backend `%s'\n"),
1230 db_lib_name);
1232 return;
1233 }
1235
1237 "peerstore",
1238 "USE_INCLUDED_HELLOS");
1239 if (GNUNET_SYSERR == use_included)
1240 use_included = GNUNET_NO;
1241 if (GNUNET_YES == use_included)
1242 {
1245 GNUNET_asprintf (&peerdir, "%shellos", ip);
1246 GNUNET_free (ip);
1247
1249 _ ("Importing HELLOs from `%s'\n"),
1250 peerdir);
1251
1254 NULL);
1255 GNUNET_free (peerdir);
1256 }
1257 else
1258 {
1260 _ ("Skipping import of included HELLOs\n"));
1261 }
1263
1265}
1266
1267
1274 &client_disconnect_cb, NULL,
1276 struct PeerstoreRecordMessage, NULL),
1277 GNUNET_MQ_hd_var_size (iterate_start,
1279 struct PeerstoreIterationStartMessage, NULL),
1280 GNUNET_MQ_hd_fixed_size (iterate_stop,
1282 struct PeerstoreIterationStopMessage, NULL),
1283 GNUNET_MQ_hd_fixed_size (iterate_next,
1286 NULL),
1287 GNUNET_MQ_hd_var_size (monitor_start,
1290 NULL),
1291 GNUNET_MQ_hd_fixed_size (monitor_next,
1294 NULL),
1296
1297
1298/* end of gnunet-service-peerstore.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
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.
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 shutdown_task(void *cls)
Task run during shutdown.
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.
GNUNET_SERVICE_MAIN(GNUNET_OS_project_data_gnunet(), "peerstore", GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(store, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE, struct PeerstoreRecordMessage, NULL), GNUNET_MQ_hd_var_size(iterate_start, GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_START, struct PeerstoreIterationStartMessage, NULL), GNUNET_MQ_hd_fixed_size(iterate_stop, GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_STOP, struct PeerstoreIterationStopMessage, NULL), GNUNET_MQ_hd_fixed_size(iterate_next, GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_NEXT, struct PeerstoreIterationNextMessage, NULL), GNUNET_MQ_hd_var_size(monitor_start, GNUNET_MESSAGE_TYPE_PEERSTORE_MONITOR_START, struct PeerstoreMonitorStartMessage, NULL), GNUNET_MQ_hd_fixed_size(monitor_next, GNUNET_MESSAGE_TYPE_PEERSTORE_MONITOR_NEXT, struct PeerstoreMonitorNextMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static void handle_iterate_stop(void *cls, const struct PeerstoreIterationStopMessage *zis_msg)
Handles a #GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATION_STOP message.
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_PeerIdentity pid
Identity of the peer we transmit to / connect to.
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:520
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:674
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:826
#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:435
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg)
Parse msg.
Definition: hello-uri.c:471
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:619
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:412
#define GNUNET_log(kind,...)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
#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_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:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
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.
Definition: gnunet_mq_lib.h:76
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#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:567
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:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
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:1304
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:1277
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2483
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2418
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
@ 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.
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
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:552
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
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:1221
Context for parsing HELLOs.
Definition: hello-uri.c:258
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)
Single PEERSTORE record.
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:136
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.