gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] branch master updated: GNS: Implement Tombstone logic


From: gnunet
Subject: [gnunet] branch master updated: GNS: Implement Tombstone logic
Date: Sat, 05 Feb 2022 15:39:14 +0100

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new ee865f851 GNS: Implement Tombstone logic
ee865f851 is described below

commit ee865f851ca4b173da8d00e87a0ad446efc8037e
Author: Martin Schanzenbach <schanzen@gnunet.org>
AuthorDate: Sat Feb 5 00:50:38 2022 +0100

    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.
---
 contrib/gana                               |   2 +-
 src/include/gnunet_gnsrecord_lib.h         |  15 +++
 src/include/gnunet_namestore_service.h     |  33 ++++++
 src/namestore/gnunet-service-namestore.c   |  97 +++++++++++++---
 src/namestore/namestore.h                  |   6 +-
 src/namestore/namestore_api.c              |  50 +++++---
 src/zonemaster/gnunet-service-zonemaster.c | 179 ++++++++++++++++++++++++++---
 7 files changed, 332 insertions(+), 50 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index 8bdb18073..6b74d0faa 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 8bdb180732314481667944cb90c1f3b148bd0088
+Subproject commit 6b74d0faa173bbb220cdd82dcf3915dadd241e1e
diff --git a/src/include/gnunet_gnsrecord_lib.h 
b/src/include/gnunet_gnsrecord_lib.h
index 2b2bd4952..7d30055fc 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -299,6 +299,21 @@ struct GNUNET_GNSRECORD_ReverseRecord
   /* followed by the name the delegator uses to refer to our namespace */
 };
 
+
+/**
+ * Tombstone record.
+ * In case of deletion of all resource records under a label, the 
implementation
+ * MUST keep track of the last absolute expiration time of the last published
+ * resource block. Implementations MAY use a PADDING record as a tombstone that
+ * preserves the last absolute expiration time, but then MUST take care to not
+ * publish a block with just a PADDING record. When new records are added under
+ * this label later, the implementation MUST ensure that the expiration times
+ * are after the last published block.
+ */
+struct GNUNET_GNSRECORD_TombstoneRecord
+{
+  struct GNUNET_TIME_AbsoluteNBO time_of_death;
+};
 GNUNET_NETWORK_STRUCT_END
 
 
diff --git a/src/include/gnunet_namestore_service.h 
b/src/include/gnunet_namestore_service.h
index 2482b97a5..7db5e9d9e 100644
--- a/src/include/gnunet_namestore_service.h
+++ b/src/include/gnunet_namestore_service.h
@@ -134,6 +134,39 @@ GNUNET_NAMESTORE_records_store (struct 
GNUNET_NAMESTORE_Handle *h,
                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
                                 void *cont_cls);
 
+/**
+ * Store an item in the namestore.  If the item is already present,
+ * it is replaced with the new record.  Use an empty array to
+ * remove all records under the given name.
+ *
+ * The continuation is called after the value has been stored in the
+ * database. Monitors may be notified asynchronously (basically with
+ * a buffer). However, if any monitor is consistently too slow to
+ * keep up with the changes, calling @a cont will be delayed until the
+ * monitors do keep up.
+ *
+ * @param h handle to the namestore
+ * @param pkey private key of the zone
+ * @param label name that is being mapped
+ * @param rd_count number of records in the 'rd' array
+ * @param rd array of records with data to store
+ * @param is_zonemaster update tombstones, do not process monitors
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+struct GNUNET_NAMESTORE_QueueEntry *
+GNUNET_NAMESTORE_records_store_ (struct GNUNET_NAMESTORE_Handle *h,
+                                 const struct GNUNET_IDENTITY_PrivateKey *pkey,
+                                 const char *label,
+                                 unsigned int rd_count,
+                                 const struct GNUNET_GNSRECORD_Data *rd,
+                                 int is_zonemaster,
+                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
+                                 void *cont_cls);
+
+
+
 
 /**
  * Process a record that was stored in the namestore.
diff --git a/src/namestore/gnunet-service-namestore.c 
b/src/namestore/gnunet-service-namestore.c
index 3842621ae..cebdf38c5 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -951,12 +951,12 @@ refresh_block (struct NamestoreClient *nc,
   exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res);
   if (cache_keys)
     GNUNET_assert (GNUNET_OK ==
-      GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name,
-                                      res, res_count, &block));
+                   GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name,
+                                                   res, res_count, &block));
   else
     GNUNET_assert (GNUNET_OK ==
-      GNUNET_GNSRECORD_block_create (zone_key, exp_time, name,
-                                     res, res_count, &block));
+                   GNUNET_GNSRECORD_block_create (zone_key, exp_time, name,
+                                                  res, res_count, &block));
   GNUNET_assert (NULL != block);
   GNUNET_IDENTITY_key_get_public (zone_key, &pkey);
   GNUNET_log (
@@ -974,7 +974,7 @@ refresh_block (struct NamestoreClient *nc,
   cop->nc = nc;
   cop->zi = zi;
   if (NULL != zi)
-    zi->cache_ops++;
+    zi->cache_ops ++;
   cop->rid = rid;
   GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop);
   cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
@@ -1341,7 +1341,6 @@ check_record_lookup (void *cls, const struct 
LabelLookupMessage *ll_msg)
   return GNUNET_OK;
 }
 
-
 /**
  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
  *
@@ -1451,6 +1450,39 @@ check_record_store (void *cls, const struct 
RecordStoreMessage *rp_msg)
 }
 
 
+/**
+ * Check if set contains a tombstone, store if necessary
+ *
+ * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if 
found)
+ * @param seq sequence number of the record, MUST NOT BE ZERO
+ * @param private_key the private key of the zone (unused)
+ * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
+ * @param rd_count number of records in @a rd
+ * @param rd records stored under @a label in the zone
+ */
+static void
+lookup_tombstone_it (void *cls,
+                     uint64_t seq,
+                     const struct GNUNET_IDENTITY_PrivateKey *private_key,
+                     const char *label,
+                     unsigned int rd_count,
+                     const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct GNUNET_GNSRECORD_TombstoneRecord *ts = cls;
+
+  (void) private_key;
+  GNUNET_assert (0 != seq);
+  for (unsigned int c = 0; c < rd_count; c++)
+  {
+    if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[c].record_type)
+    {
+      memcpy (ts, rd[c].data, rd[c].data_size);
+      return;
+    }
+  }
+}
+
+
 /**
  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
  *
@@ -1470,14 +1502,15 @@ handle_record_store (void *cls, const struct 
RecordStoreMessage *rp_msg)
   unsigned int rd_count;
   int res;
   struct StoreActivity *sa;
+  struct GNUNET_GNSRECORD_TombstoneRecord tombstone;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Received NAMESTORE_RECORD_STORE message\n");
+  tombstone.time_of_death.abs_value_us__ = 0;
   rid = ntohl (rp_msg->gns_header.r_id);
   name_len = ntohs (rp_msg->name_len);
   rd_count = ntohs (rp_msg->rd_count);
   rd_ser_len = ntohs (rp_msg->rd_len);
-  GNUNET_break (0 == ntohs (rp_msg->reserved));
   name_tmp = (const char *) &rp_msg[1];
   rd_ser = &name_tmp[name_len];
   {
@@ -1513,8 +1546,8 @@ handle_record_store (void *cls, const struct 
RecordStoreMessage *rp_msg)
         (GNUNET_NO == GSN_database->lookup_records (GSN_database->cls,
                                                     &rp_msg->private_key,
                                                     conv_name,
-                                                    NULL,
-                                                    0)))
+                                                    &lookup_tombstone_it,
+                                                    &tombstone)))
     {
       /* This name does not exist, so cannot be removed */
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1525,16 +1558,34 @@ handle_record_store (void *cls, const struct 
RecordStoreMessage *rp_msg)
     else
     {
       /* remove "NICK" records, unless this is for the
-       #GNUNET_GNS_EMPTY_LABEL_AT label */
-      struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)];
+       #GNUNET_GNS_EMPTY_LABEL_AT label
+       Also, add or update tombstone record if this is a zonemaster request.
+       Also, add existing tombstone record to set if this is not a zonemaster
+       request if one existed in the old set.
+       This is why we (may) need one additional record */
+      struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count) + 1];
       unsigned int rd_clean_off;
       int have_nick;
+      int have_tombstone;
 
       rd_clean_off = 0;
       have_nick = GNUNET_NO;
+      have_tombstone = GNUNET_NO;
       for (unsigned int i = 0; i < rd_count; i++)
       {
         rd_clean[rd_clean_off] = rd[i];
+        if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type))
+          rd_clean[rd_clean_off].flags |= GNUNET_GNSRECORD_RF_CRITICAL;
+        /* Do not allow to set tombstone records unless zonemaster */
+        if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
+        {
+          if (1 == ntohs (rp_msg->is_zonemaster))
+          {
+            have_tombstone = GNUNET_YES;
+            rd_clean_off++;
+          }
+          continue;
+        }
         if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) ||
             (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type))
           rd_clean_off++;
@@ -1545,8 +1596,24 @@ handle_record_store (void *cls, const struct 
RecordStoreMessage *rp_msg)
           cache_nick (&rp_msg->private_key, &rd[i]);
           have_nick = GNUNET_YES;
         }
-        if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type))
-          rd_clean[i].flags |= GNUNET_GNSRECORD_RF_CRITICAL;
+      }
+      /* At this point we are either zonemaster and have set a new tombstone
+       * (have_tombstone) or we are not zonemaster and we may want to
+       * add the old tombstone (if there was any and if it is not already
+       * old).
+       */
+      if ((GNUNET_NO == have_tombstone) &&
+          GNUNET_TIME_absolute_cmp (GNUNET_TIME_absolute_get (), (<),
+                                    GNUNET_TIME_absolute_ntoh (
+                                      tombstone.time_of_death)))
+      {
+        rd_clean[rd_clean_off].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE;
+        rd_clean[rd_clean_off].expiration_time =
+          GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
+        rd_clean[rd_clean_off].data = &tombstone;
+        rd_clean[rd_clean_off].data_size = sizeof (tombstone);
+        rd_clean[rd_clean_off].flags |= GNUNET_GNSRECORD_RF_PRIVATE;
+        rd_clean_off++;
       }
       if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
           (GNUNET_NO == have_nick))
@@ -1561,9 +1628,9 @@ handle_record_store (void *cls, const struct 
RecordStoreMessage *rp_msg)
                                          rd_clean);
     }
 
-    if (GNUNET_OK != res)
+    if ((GNUNET_OK != res) || (1 == ntohs (rp_msg->is_zonemaster)))
     {
-      /* store not successful, not need to tell monitors */
+      /* store not successful or zonemaster, not need to tell monitors */
       send_store_response (nc, res, rid);
       GNUNET_SERVICE_client_continue (nc->client);
       GNUNET_free (conv_name);
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
index fd9a8ed47..bcc8f5d4e 100644
--- a/src/namestore/namestore.h
+++ b/src/namestore/namestore.h
@@ -83,9 +83,11 @@ struct RecordStoreMessage
   uint16_t rd_count GNUNET_PACKED;
 
   /**
-   * always zero (for alignment)
+   * This is a zonemaster request.
+   * It means more authoritative tombstone processing
+   * and not notification of monitors.
    */
-  uint16_t reserved GNUNET_PACKED;
+  uint16_t is_zonemaster GNUNET_PACKED;
 
   /**
    * The private key of the authority.
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index b24db9b26..935357d36 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -969,28 +969,14 @@ warn_delay (void *cls)
   GNUNET_NAMESTORE_cancel (qe);
 }
 
-
-/**
- * Store an item in the namestore.  If the item is already present,
- * it is replaced with the new record.  Use an empty array to
- * remove all records under the given name.
- *
- * @param h handle to the namestore
- * @param pkey private key of the zone
- * @param label name that is being mapped (at most 255 characters long)
- * @param rd_count number of records in the @a rd array
- * @param rd array of records with data to store
- * @param cont continuation to call when done
- * @param cont_cls closure for @a cont
- * @return handle to abort the request
- */
 struct GNUNET_NAMESTORE_QueueEntry *
-GNUNET_NAMESTORE_records_store (
+GNUNET_NAMESTORE_records_store_ (
   struct GNUNET_NAMESTORE_Handle *h,
   const struct GNUNET_IDENTITY_PrivateKey *pkey,
   const char *label,
   unsigned int rd_count,
   const struct GNUNET_GNSRECORD_Data *rd,
+  int is_zonemaster,
   GNUNET_NAMESTORE_ContinuationWithStatus cont,
   void *cont_cls)
 {
@@ -1037,7 +1023,7 @@ GNUNET_NAMESTORE_records_store (
   msg->name_len = htons (name_len);
   msg->rd_count = htons (rd_count);
   msg->rd_len = htons (rd_ser_len);
-  msg->reserved = htons (0);
+  msg->is_zonemaster = (GNUNET_YES == is_zonemaster) ? ntohs(1) : ntohs(0);
   msg->private_key = *pkey;
 
   name_tmp = (char *) &msg[1];
@@ -1070,6 +1056,36 @@ GNUNET_NAMESTORE_records_store (
   return qe;
 }
 
+/**
+ * Store an item in the namestore.  If the item is already present,
+ * it is replaced with the new record.  Use an empty array to
+ * remove all records under the given name.
+ *
+ * @param h handle to the namestore
+ * @param pkey private key of the zone
+ * @param label name that is being mapped (at most 255 characters long)
+ * @param rd_count number of records in the @a rd array
+ * @param rd array of records with data to store
+ * @param cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+struct GNUNET_NAMESTORE_QueueEntry *
+GNUNET_NAMESTORE_records_store (
+  struct GNUNET_NAMESTORE_Handle *h,
+  const struct GNUNET_IDENTITY_PrivateKey *pkey,
+  const char *label,
+  unsigned int rd_count,
+  const struct GNUNET_GNSRECORD_Data *rd,
+  GNUNET_NAMESTORE_ContinuationWithStatus cont,
+  void *cont_cls)
+{
+  return GNUNET_NAMESTORE_records_store_ (h, pkey, label, rd_count, rd,
+                                          GNUNET_NO, cont, cont_cls);
+}
+
+
+
 
 /**
  * Lookup an item in the namestore.
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 @@
  */
 #define DHT_GNS_REPLICATION_LEVEL 5
 
+/**
+ * Handle for tombston updates which are executed for each published
+ * record set.
+ */
+struct TombstoneActivity
+{
+  /**
+   * Kept in a DLL.
+   */
+  struct TombstoneActivity *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct TombstoneActivity *prev;
+
+  /**
+   * Handle for the store operation.
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+};
+
 
 /**
  * Handle for DHT PUT activity triggered from the namestore monitor.
@@ -148,6 +171,16 @@ static struct DhtPutActivity *it_head;
  */
 static struct DhtPutActivity *it_tail;
 
+/**
+ * Head of the tombstone operations
+ */
+static struct TombstoneActivity *ta_head;
+
+/**
+ * Tail of the tombstone operations
+ */
+static struct TombstoneActivity *ta_tail;
+
 /**
  * Number of entries in the DHT queue #it_head.
  */
@@ -248,6 +281,7 @@ static void
 shutdown_task (void *cls)
 {
   struct DhtPutActivity *ma;
+  struct TombstoneActivity *ta;
 
   (void) cls;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -262,6 +296,14 @@ shutdown_task (void *cls)
     dht_queue_length--;
     GNUNET_free (ma);
   }
+  while (NULL != (ta = ta_head))
+  {
+    GNUNET_NAMESTORE_cancel (ta->ns_qe);
+    GNUNET_CONTAINER_DLL_remove (ta_head,
+                                 ta_tail,
+                                 ta);
+    GNUNET_free (ta);
+  }
   if (NULL != statistics)
   {
     GNUNET_STATISTICS_destroy (statistics,
@@ -535,22 +577,33 @@ dht_put_continuation (void *cls)
  * @param rd input records
  * @param rd_count size of the @a rd and @a rd_public arrays
  * @param rd_public where to write the converted records
+ * @param expire the expiration of the block
  * @return number of records written to @a rd_public
  */
 static unsigned int
 convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
                             unsigned int rd_count,
-                            struct GNUNET_GNSRECORD_Data *rd_public)
+                            struct GNUNET_GNSRECORD_Data *rd_public,
+                            struct GNUNET_TIME_Absolute *expiry)
 {
+  const struct GNUNET_GNSRECORD_TombstoneRecord *tombstone;
+  struct GNUNET_TIME_Absolute expiry_tombstone;
   struct GNUNET_TIME_Absolute now;
   unsigned int rd_public_count;
 
   rd_public_count = 0;
+  tombstone = NULL;
   now = GNUNET_TIME_absolute_get ();
   for (unsigned int i = 0; i < rd_count; i++)
   {
     if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
       continue;
+    /* Should always be private but just to be sure */
+    if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
+    {
+      tombstone = rd[i].data;
+      continue;
+    }
     if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
         (rd[i].expiration_time < now.abs_value_us))
       continue;   /* record already expired, skip it */
@@ -568,6 +621,21 @@ convert_records_for_export (const struct 
GNUNET_GNSRECORD_Data *rd,
       rd_public[rd_public_count].flags |= GNUNET_GNSRECORD_RF_CRITICAL;
     rd_public_count++;
   }
+
+  *expiry = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
+                                                         rd_public);
+
+  /* We need to check if the tombstone has an expiration in the fututre
+   * which would mean there was a block published under this label
+   * previously that is still valid. In this case we MUST NOT publish this
+   * block
+   */
+  if (NULL != tombstone)
+  {
+    expiry_tombstone = GNUNET_TIME_absolute_ntoh (tombstone->time_of_death);
+    if (GNUNET_TIME_absolute_cmp (*expiry,<=,expiry_tombstone))
+      return 0;
+  }
   return rd_public_count;
 }
 
@@ -587,30 +655,28 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey 
*key,
                  const char *label,
                  const struct GNUNET_GNSRECORD_Data *rd_public,
                  unsigned int rd_public_count,
+                 const struct GNUNET_TIME_Absolute expire,
                  struct DhtPutActivity *ma)
 {
   struct GNUNET_GNSRECORD_Block *block;
   struct GNUNET_HashCode query;
-  struct GNUNET_TIME_Absolute expire;
   size_t block_size;
   struct GNUNET_DHT_PutHandle *ret;
 
-  expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
-                                                        rd_public);
   if (cache_keys)
     GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key,
-                                            expire,
-                                            label,
-                                            rd_public,
-                                            rd_public_count,
-                                            &block));
+                                                                expire,
+                                                                label,
+                                                                rd_public,
+                                                                
rd_public_count,
+                                                                &block));
   else
     GNUNET_assert (GNUNET_OK ==  GNUNET_GNSRECORD_block_create (key,
-                                           expire,
-                                           label,
-                                           rd_public,
-                                           rd_public_count,
-                                           &block));
+                                                                expire,
+                                                                label,
+                                                                rd_public,
+                                                                
rd_public_count,
+                                                                &block));
   if (NULL == block)
   {
     GNUNET_break (0);
@@ -717,6 +783,74 @@ zone_iteration_finished (void *cls)
   }
 }
 
+static void
+ts_store_cont (void *cls, int32_t success, const char *emsg)
+{
+  struct TombstoneActivity *ta = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Tombstone update complete\n");
+  GNUNET_CONTAINER_DLL_remove (ta_head,
+                               ta_tail,
+                               ta);
+  GNUNET_free (ta);
+
+}
+
+/**
+ * Update tombstone records.
+ *
+ * @param key key of the zone
+ * @param label label to store under
+ * @param rd_public public record data
+ * @param rd_public_count number of records in @a rd_public
+ * @param expire the expiration time for the tombstone
+ * @param ta handle for the put operation
+ * @return Namestore queue entry, NULL on error
+ */
+static struct GNUNET_NAMESTORE_QueueEntry *
+touch_tombstone (const struct GNUNET_IDENTITY_PrivateKey *key,
+                 const char *label,
+                 const struct GNUNET_GNSRECORD_Data *rd_original,
+                 unsigned int rd_count_original,
+                 const struct GNUNET_TIME_Absolute expire,
+                 struct TombstoneActivity *ta)
+{
+  struct GNUNET_TIME_AbsoluteNBO exp_nbo;
+  struct GNUNET_GNSRECORD_Data rd[rd_count_original + 1];
+  int tombstone_exists = GNUNET_NO;
+  unsigned int rd_count;
+
+  exp_nbo = GNUNET_TIME_absolute_hton (expire);
+  for (rd_count = 0; rd_count < rd_count_original; rd_count++)
+  {
+    memcpy (&rd[rd_count], &rd_original[rd_count],
+            sizeof (struct GNUNET_GNSRECORD_Data));
+    if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[rd_count].record_type)
+    {
+      rd[rd_count].data = &exp_nbo;
+      tombstone_exists = GNUNET_YES;
+    }
+  }
+  if (GNUNET_NO == tombstone_exists)
+  {
+    rd[rd_count].data = &exp_nbo;
+    rd[rd_count].data_size = sizeof (exp_nbo);
+    rd[rd_count].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE;
+    rd[rd_count].flags = GNUNET_GNSRECORD_RF_PRIVATE;
+    rd[rd_count].expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
+    rd_count++;
+  }
+  return GNUNET_NAMESTORE_records_store_ (namestore_handle,
+                                                key,
+                                                label,
+                                                rd_count,
+                                                rd,
+                                                GNUNET_YES,
+                                                &ts_store_cont,
+                                                ta);
+}
+
 
 /**
  * Function used to put all records successively into the DHT.
@@ -737,12 +871,15 @@ put_gns_record (void *cls,
   struct GNUNET_GNSRECORD_Data rd_public[rd_count];
   unsigned int rd_public_count;
   struct DhtPutActivity *ma;
+  struct TombstoneActivity *ta;
+  struct GNUNET_TIME_Absolute expire;
 
   (void) cls;
   ns_iteration_left--;
   rd_public_count = convert_records_for_export (rd,
                                                 rd_count,
-                                                rd_public);
+                                                rd_public,
+                                                &expire);
   if (0 == rd_public_count)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -753,13 +890,25 @@ put_gns_record (void *cls,
   /* We got a set of records to publish */
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Starting DHT PUT\n");
+
   ma = GNUNET_new (struct DhtPutActivity);
   ma->start_date = GNUNET_TIME_absolute_get ();
   ma->ph = perform_dht_put (key,
                             label,
                             rd_public,
                             rd_public_count,
+                            expire,
                             ma);
+  ta = GNUNET_new (struct TombstoneActivity);
+  ta->ns_qe = touch_tombstone (key,
+                               label,
+                               rd,
+                               rd_count,
+                               expire,
+                               ta);
+  GNUNET_CONTAINER_DLL_insert_tail (ta_head,
+                                    ta_tail,
+                                    ta);
   put_cnt++;
   if (0 == put_cnt % DELTA_INTERVAL)
     update_velocity (DELTA_INTERVAL);

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]