aboutsummaryrefslogtreecommitdiff
path: root/src/zonemaster/gnunet-service-zonemaster.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-02-05 00:50:38 +0100
committerMartin Schanzenbach <schanzen@gnunet.org>2022-02-05 15:38:39 +0100
commitee865f851ca4b173da8d00e87a0ad446efc8037e (patch)
tree92a627afa5799d78df0fd5b09a711ca3b89a8b6b /src/zonemaster/gnunet-service-zonemaster.c
parent65f9e37ce036acdfab29b25b9b6f69de1b126962 (diff)
downloadgnunet-ee865f851ca4b173da8d00e87a0ad446efc8037e.tar.gz
gnunet-ee865f851ca4b173da8d00e87a0ad446efc8037e.zip
GNS: Implement Tombstone logic
GNS: Namestore zonemaster record store processing ZONEMASTER: Do not publish records if tombstone expires in the future NAMESTORE: Purge old tombstones.
Diffstat (limited to 'src/zonemaster/gnunet-service-zonemaster.c')
-rw-r--r--src/zonemaster/gnunet-service-zonemaster.c179
1 files changed, 164 insertions, 15 deletions
diff --git a/src/zonemaster/gnunet-service-zonemaster.c b/src/zonemaster/gnunet-service-zonemaster.c
index 9ff1a97b8..e478ceeab 100644
--- a/src/zonemaster/gnunet-service-zonemaster.c
+++ b/src/zonemaster/gnunet-service-zonemaster.c
@@ -90,6 +90,29 @@
90 */ 90 */
91#define DHT_GNS_REPLICATION_LEVEL 5 91#define DHT_GNS_REPLICATION_LEVEL 5
92 92
93/**
94 * Handle for tombston updates which are executed for each published
95 * record set.
96 */
97struct TombstoneActivity
98{
99 /**
100 * Kept in a DLL.
101 */
102 struct TombstoneActivity *next;
103
104 /**
105 * Kept in a DLL.
106 */
107 struct TombstoneActivity *prev;
108
109 /**
110 * Handle for the store operation.
111 */
112 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
113
114};
115
93 116
94/** 117/**
95 * Handle for DHT PUT activity triggered from the namestore monitor. 118 * Handle for DHT PUT activity triggered from the namestore monitor.
@@ -149,6 +172,16 @@ static struct DhtPutActivity *it_head;
149static struct DhtPutActivity *it_tail; 172static struct DhtPutActivity *it_tail;
150 173
151/** 174/**
175 * Head of the tombstone operations
176 */
177static struct TombstoneActivity *ta_head;
178
179/**
180 * Tail of the tombstone operations
181 */
182static struct TombstoneActivity *ta_tail;
183
184/**
152 * Number of entries in the DHT queue #it_head. 185 * Number of entries in the DHT queue #it_head.
153 */ 186 */
154static unsigned int dht_queue_length; 187static unsigned int dht_queue_length;
@@ -248,6 +281,7 @@ static void
248shutdown_task (void *cls) 281shutdown_task (void *cls)
249{ 282{
250 struct DhtPutActivity *ma; 283 struct DhtPutActivity *ma;
284 struct TombstoneActivity *ta;
251 285
252 (void) cls; 286 (void) cls;
253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -262,6 +296,14 @@ shutdown_task (void *cls)
262 dht_queue_length--; 296 dht_queue_length--;
263 GNUNET_free (ma); 297 GNUNET_free (ma);
264 } 298 }
299 while (NULL != (ta = ta_head))
300 {
301 GNUNET_NAMESTORE_cancel (ta->ns_qe);
302 GNUNET_CONTAINER_DLL_remove (ta_head,
303 ta_tail,
304 ta);
305 GNUNET_free (ta);
306 }
265 if (NULL != statistics) 307 if (NULL != statistics)
266 { 308 {
267 GNUNET_STATISTICS_destroy (statistics, 309 GNUNET_STATISTICS_destroy (statistics,
@@ -535,22 +577,33 @@ dht_put_continuation (void *cls)
535 * @param rd input records 577 * @param rd input records
536 * @param rd_count size of the @a rd and @a rd_public arrays 578 * @param rd_count size of the @a rd and @a rd_public arrays
537 * @param rd_public where to write the converted records 579 * @param rd_public where to write the converted records
580 * @param expire the expiration of the block
538 * @return number of records written to @a rd_public 581 * @return number of records written to @a rd_public
539 */ 582 */
540static unsigned int 583static unsigned int
541convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd, 584convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
542 unsigned int rd_count, 585 unsigned int rd_count,
543 struct GNUNET_GNSRECORD_Data *rd_public) 586 struct GNUNET_GNSRECORD_Data *rd_public,
587 struct GNUNET_TIME_Absolute *expiry)
544{ 588{
589 const struct GNUNET_GNSRECORD_TombstoneRecord *tombstone;
590 struct GNUNET_TIME_Absolute expiry_tombstone;
545 struct GNUNET_TIME_Absolute now; 591 struct GNUNET_TIME_Absolute now;
546 unsigned int rd_public_count; 592 unsigned int rd_public_count;
547 593
548 rd_public_count = 0; 594 rd_public_count = 0;
595 tombstone = NULL;
549 now = GNUNET_TIME_absolute_get (); 596 now = GNUNET_TIME_absolute_get ();
550 for (unsigned int i = 0; i < rd_count; i++) 597 for (unsigned int i = 0; i < rd_count; i++)
551 { 598 {
552 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) 599 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
553 continue; 600 continue;
601 /* Should always be private but just to be sure */
602 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
603 {
604 tombstone = rd[i].data;
605 continue;
606 }
554 if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) && 607 if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
555 (rd[i].expiration_time < now.abs_value_us)) 608 (rd[i].expiration_time < now.abs_value_us))
556 continue; /* record already expired, skip it */ 609 continue; /* record already expired, skip it */
@@ -568,6 +621,21 @@ convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
568 rd_public[rd_public_count].flags |= GNUNET_GNSRECORD_RF_CRITICAL; 621 rd_public[rd_public_count].flags |= GNUNET_GNSRECORD_RF_CRITICAL;
569 rd_public_count++; 622 rd_public_count++;
570 } 623 }
624
625 *expiry = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
626 rd_public);
627
628 /* We need to check if the tombstone has an expiration in the fututre
629 * which would mean there was a block published under this label
630 * previously that is still valid. In this case we MUST NOT publish this
631 * block
632 */
633 if (NULL != tombstone)
634 {
635 expiry_tombstone = GNUNET_TIME_absolute_ntoh (tombstone->time_of_death);
636 if (GNUNET_TIME_absolute_cmp (*expiry,<=,expiry_tombstone))
637 return 0;
638 }
571 return rd_public_count; 639 return rd_public_count;
572} 640}
573 641
@@ -587,30 +655,28 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
587 const char *label, 655 const char *label,
588 const struct GNUNET_GNSRECORD_Data *rd_public, 656 const struct GNUNET_GNSRECORD_Data *rd_public,
589 unsigned int rd_public_count, 657 unsigned int rd_public_count,
658 const struct GNUNET_TIME_Absolute expire,
590 struct DhtPutActivity *ma) 659 struct DhtPutActivity *ma)
591{ 660{
592 struct GNUNET_GNSRECORD_Block *block; 661 struct GNUNET_GNSRECORD_Block *block;
593 struct GNUNET_HashCode query; 662 struct GNUNET_HashCode query;
594 struct GNUNET_TIME_Absolute expire;
595 size_t block_size; 663 size_t block_size;
596 struct GNUNET_DHT_PutHandle *ret; 664 struct GNUNET_DHT_PutHandle *ret;
597 665
598 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
599 rd_public);
600 if (cache_keys) 666 if (cache_keys)
601 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key, 667 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key,
602 expire, 668 expire,
603 label, 669 label,
604 rd_public, 670 rd_public,
605 rd_public_count, 671 rd_public_count,
606 &block)); 672 &block));
607 else 673 else
608 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key, 674 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key,
609 expire, 675 expire,
610 label, 676 label,
611 rd_public, 677 rd_public,
612 rd_public_count, 678 rd_public_count,
613 &block)); 679 &block));
614 if (NULL == block) 680 if (NULL == block)
615 { 681 {
616 GNUNET_break (0); 682 GNUNET_break (0);
@@ -717,6 +783,74 @@ zone_iteration_finished (void *cls)
717 } 783 }
718} 784}
719 785
786static void
787ts_store_cont (void *cls, int32_t success, const char *emsg)
788{
789 struct TombstoneActivity *ta = cls;
790
791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
792 "Tombstone update complete\n");
793 GNUNET_CONTAINER_DLL_remove (ta_head,
794 ta_tail,
795 ta);
796 GNUNET_free (ta);
797
798}
799
800/**
801 * Update tombstone records.
802 *
803 * @param key key of the zone
804 * @param label label to store under
805 * @param rd_public public record data
806 * @param rd_public_count number of records in @a rd_public
807 * @param expire the expiration time for the tombstone
808 * @param ta handle for the put operation
809 * @return Namestore queue entry, NULL on error
810 */
811static struct GNUNET_NAMESTORE_QueueEntry *
812touch_tombstone (const struct GNUNET_IDENTITY_PrivateKey *key,
813 const char *label,
814 const struct GNUNET_GNSRECORD_Data *rd_original,
815 unsigned int rd_count_original,
816 const struct GNUNET_TIME_Absolute expire,
817 struct TombstoneActivity *ta)
818{
819 struct GNUNET_TIME_AbsoluteNBO exp_nbo;
820 struct GNUNET_GNSRECORD_Data rd[rd_count_original + 1];
821 int tombstone_exists = GNUNET_NO;
822 unsigned int rd_count;
823
824 exp_nbo = GNUNET_TIME_absolute_hton (expire);
825 for (rd_count = 0; rd_count < rd_count_original; rd_count++)
826 {
827 memcpy (&rd[rd_count], &rd_original[rd_count],
828 sizeof (struct GNUNET_GNSRECORD_Data));
829 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[rd_count].record_type)
830 {
831 rd[rd_count].data = &exp_nbo;
832 tombstone_exists = GNUNET_YES;
833 }
834 }
835 if (GNUNET_NO == tombstone_exists)
836 {
837 rd[rd_count].data = &exp_nbo;
838 rd[rd_count].data_size = sizeof (exp_nbo);
839 rd[rd_count].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE;
840 rd[rd_count].flags = GNUNET_GNSRECORD_RF_PRIVATE;
841 rd[rd_count].expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
842 rd_count++;
843 }
844 return GNUNET_NAMESTORE_records_store_ (namestore_handle,
845 key,
846 label,
847 rd_count,
848 rd,
849 GNUNET_YES,
850 &ts_store_cont,
851 ta);
852}
853
720 854
721/** 855/**
722 * Function used to put all records successively into the DHT. 856 * Function used to put all records successively into the DHT.
@@ -737,12 +871,15 @@ put_gns_record (void *cls,
737 struct GNUNET_GNSRECORD_Data rd_public[rd_count]; 871 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
738 unsigned int rd_public_count; 872 unsigned int rd_public_count;
739 struct DhtPutActivity *ma; 873 struct DhtPutActivity *ma;
874 struct TombstoneActivity *ta;
875 struct GNUNET_TIME_Absolute expire;
740 876
741 (void) cls; 877 (void) cls;
742 ns_iteration_left--; 878 ns_iteration_left--;
743 rd_public_count = convert_records_for_export (rd, 879 rd_public_count = convert_records_for_export (rd,
744 rd_count, 880 rd_count,
745 rd_public); 881 rd_public,
882 &expire);
746 if (0 == rd_public_count) 883 if (0 == rd_public_count)
747 { 884 {
748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -753,13 +890,25 @@ put_gns_record (void *cls,
753 /* We got a set of records to publish */ 890 /* We got a set of records to publish */
754 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
755 "Starting DHT PUT\n"); 892 "Starting DHT PUT\n");
893
756 ma = GNUNET_new (struct DhtPutActivity); 894 ma = GNUNET_new (struct DhtPutActivity);
757 ma->start_date = GNUNET_TIME_absolute_get (); 895 ma->start_date = GNUNET_TIME_absolute_get ();
758 ma->ph = perform_dht_put (key, 896 ma->ph = perform_dht_put (key,
759 label, 897 label,
760 rd_public, 898 rd_public,
761 rd_public_count, 899 rd_public_count,
900 expire,
762 ma); 901 ma);
902 ta = GNUNET_new (struct TombstoneActivity);
903 ta->ns_qe = touch_tombstone (key,
904 label,
905 rd,
906 rd_count,
907 expire,
908 ta);
909 GNUNET_CONTAINER_DLL_insert_tail (ta_head,
910 ta_tail,
911 ta);
763 put_cnt++; 912 put_cnt++;
764 if (0 == put_cnt % DELTA_INTERVAL) 913 if (0 == put_cnt % DELTA_INTERVAL)
765 update_velocity (DELTA_INTERVAL); 914 update_velocity (DELTA_INTERVAL);