add function to obtain monotonic time
authorChristian Grothoff <christian@grothoff.org>
Thu, 13 Dec 2018 16:30:08 +0000 (17:30 +0100)
committerChristian Grothoff <christian@grothoff.org>
Thu, 13 Dec 2018 16:30:16 +0000 (17:30 +0100)
src/include/gnunet_time_lib.h
src/include/gnunet_transport_communication_service.h
src/util/disk.c
src/util/gnunet-service-resolver.c
src/util/test_regex.c
src/util/test_time.c
src/util/test_tun.c
src/util/time.c

index c7a06ba23bbf7ee921f99ed6816c5db89efc1fcf..674a955344a12505b8df6d55d927f15bbc0463da 100644 (file)
@@ -365,7 +365,8 @@ GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future);
  *        assuming it continues at the same speed
  */
 struct GNUNET_TIME_Relative
-GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, uint64_t finished,
+GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start,
+                          uint64_t finished,
                            uint64_t total);
 
 
@@ -565,6 +566,34 @@ unsigned int
 GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at);
 
 
+/**
+ * A configuration object.
+ */
+struct GNUNET_CONFIGURATION_Handle;
+
+
+/**
+ * Obtain the current time and make sure it is monotonically
+ * increasing.  Guards against systems without an RTC or
+ * clocks running backwards and other nasty surprises. Does
+ * not guarantee that the returned time is near the current
+ * time returned by #GNUNET_TIME_absolute_get().  Two 
+ * subsequent calls (within a short time period) may return the
+ * same value. Persists the last returned time on disk to
+ * ensure that time never goes backwards. As a result, the
+ * resulting value can be used to check if a message is the 
+ * "most recent" value and replays of older messages (from
+ * the same origin) would be discarded.
+ * 
+ * @param cfg configuration, used to determine where to 
+ *   store the time; user can also insist RTC is working
+ *   nicely and disable the feature
+ * @return monotonically increasing time
+ */
+struct GNUNET_TIME_Absolute
+GNUNET_TIME_absolute_get_monotonic (const struct GNUNET_CONFIGURATION_Handle *cfg);
+
+
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif
index f81ee6d9a7abf797ebb00b7ce5ea5fdeb86c8c55..8cf275660c8860e3dd620febcd18921fec52b6dd 100644 (file)
@@ -102,6 +102,19 @@ enum GNUNET_TRANSPORT_CommunicatorCharacteristics {
 };
 
 
+/**
+ * Function called when the transport service has received an
+ * acknowledgement for this communicator (!) via a different return
+ * path. 
+ */
+typedef void
+(*GNUNET_TRANSPORT_CommunicatorNotify) (void *cls,
+                                       const struct GNUNET_PeerIdentity *sender,
+                                       struct GNUNET_TIME_Absolute monotonic_time,
+                                       struct GNUNET_TIME_Relative validity,
+                                       const struct GNUNET_HashCode *token                     
+                                       );
+
 /**
  * Connect to the transport service.
  *
@@ -122,7 +135,9 @@ GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle
                                       const char *addr_prefix,
                                        enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc,
                                        GNUNET_TRANSPORT_CommunicatorMqInit mq_init,
-                                       void *mq_init_cls);
+                                       void *mq_init_cls,
+                                      GNUNET_TRANSPORT_CommunicatorNotify notify_cb,
+                                      void *notify_cb_cls);
 
 
 /**
@@ -275,6 +290,28 @@ void
 GNUNET_TRANSPORT_communicator_address_remove (struct GNUNET_TRANSPORT_AddressIdentifier *ai);
 
 
+/**
+ * The communicator asks the transport service to route a message via
+ * a different path to another communicator service at another peer.
+ * This must only be done for special control traffic (as there is no
+ * flow control for this API), such as acknowledgements, and generally
+ * only be done if the communicator is uni-directional (i.e. cannot
+ * send the message back itself).
+ *
+ * @param ch handle of this communicator
+ * @param target_pid peer to send the message to
+ * @param target_comm name of the communicator to send the message to
+ */
+void
+GNUNET_TRANSPORT_communicator_notify (struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
+                                     const struct GNUNET_PeerIdentity *pid,
+                                     const char *comm,
+                                     struct GNUNET_TIME_Absolute monotonic_time,
+                                     struct GNUNET_TIME_Relative validity,
+                                     const struct GNUNET_HashCode *token
+                                     );
+
+
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif
index dc38d1137265acb29fc9c48f41e18aaa2bbb052b..d723303d84590bcc421760599e3ee6ad963f2209 100644 (file)
@@ -236,7 +236,8 @@ GNUNET_DISK_file_handle_size (struct GNUNET_DISK_FileHandle *fh,
  * @return the new position on success, #GNUNET_SYSERR otherwise
  */
 off_t
-GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, off_t offset,
+GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle *h,
+                      off_t offset,
                        enum GNUNET_DISK_Seek whence)
 {
   if (h == NULL)
@@ -1034,7 +1035,8 @@ GNUNET_DISK_fn_read (const char *fn,
  */
 ssize_t
 GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h,
-                        const void *buffer, size_t n)
+                        const void *buffer,
+                       size_t n)
 {
   if (NULL == h)
   {
index 065a224eb8657f77380c01908a6c9987e2a4d037..5f8957d8c0726fc69a8c541d185e7ddcf5e24926 100644 (file)
@@ -1123,7 +1123,6 @@ check_get (void *cls,
 
   (void) cls;
   size = ntohs (get->header.size) - sizeof (*get);
-  const char *str = &get[1];
   direction = ntohl (get->direction);
   if (GNUNET_NO == direction)
   {
index 2e7d5282801e68041f3b399ba608036639e7a688..4eb7cf87d9e3a04d835a1182a277a112a4326758 100644 (file)
@@ -21,7 +21,7 @@
  * @author Maximilian Szengel
  */
 #include "platform.h"
-#include "gnunet_tun_lib.h"
+#include "gnunet_util_lib.h"
 
 /**
  * 'wildcard', matches all possible values (for HEX encoding).
index 2ac93e01dc40ca7398016ce0b7519ea0edb0e976..80c4e53372791dccaec7786aec27da36bd754326 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2001-2013 GNUnet e.V.
+     Copyright (C) 2001-2013, 2018 GNUnet e.V.
 
      GNUnet is free software: you can redistribute it and/or modify it
      under the terms of the GNU Affero General Public License as published
@@ -223,7 +223,28 @@ main (int argc, char *argv[])
   /*check  GNUNET_TIME_absolute_max */
   GNUNET_assert (now.abs_value_us ==
                  GNUNET_TIME_absolute_max (now, last).abs_value_us);
-
+  for (unsigned int i=0;i<30;i++)
+  {
+    struct GNUNET_CONFIGURATION_Handle *cfg;
+
+    cfg = GNUNET_CONFIGURATION_create ();
+    last = GNUNET_TIME_absolute_get_monotonic (cfg);
+    now = GNUNET_TIME_absolute_get_monotonic (cfg);
+    GNUNET_assert (now.abs_value_us > last.abs_value_us);
+    (void) GNUNET_TIME_absolute_get_monotonic (NULL);
+    GNUNET_CONFIGURATION_set_value_string (cfg,
+                                          "util",
+                                          "MONOTONIC_TIME_FILENAME",
+                                          "monotonic-time.dat");
+    last = GNUNET_TIME_absolute_get_monotonic (cfg);
+    now = GNUNET_TIME_absolute_get_monotonic (cfg);
+    (void) GNUNET_TIME_absolute_get_monotonic (NULL);
+    GNUNET_assert (now.abs_value_us > last.abs_value_us);
+    GNUNET_CONFIGURATION_destroy (cfg);
+  }
+  GNUNET_break (GNUNET_OK ==
+               GNUNET_DISK_directory_remove ("monotonic-time.dat"));
+  
   return 0;
 }
 
index edbd4c05d629f1460812ad68516918f71cf4116e..429678fd5099aef6c909eaa4524d7231b5657b4e 100644 (file)
@@ -22,7 +22,7 @@
  * @author Christian Grothoff
  */
 #include "platform.h"
-#include "gnunet_tun_lib.h"
+#include "gnunet_util_lib.h"
 
 static int ret;
 
index b02c43c1b90e5c7be3c0a79b1f5f9d810a8189c5..46d3a2b6574b41a29a4b3899edf77ad6521dbdc3 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2001-2013 GNUnet e.V.
+     Copyright (C) 2001-2013, 2018 GNUnet e.V.
 
      GNUnet is free software: you can redistribute it and/or modify it
      under the terms of the GNU Affero General Public License as published
@@ -22,8 +22,7 @@
  * @brief functions for handling time and time arithmetic
  */
 #include "platform.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_time_lib.h"
+#include "gnunet_util_lib.h"
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util-time", __VA_ARGS__)
 
@@ -757,6 +756,127 @@ GNUNET_TIME_randomized_backoff(struct GNUNET_TIME_Relative rt, struct GNUNET_TIM
 }
 
 
+/**
+ * Obtain the current time and make sure it is monotonically
+ * increasing.  Guards against systems without an RTC or
+ * clocks running backwards and other nasty surprises. Does
+ * not guarantee that the returned time is near the current
+ * time returned by #GNUNET_TIME_absolute_get().  Two 
+ * subsequent calls (within a short time period) may return the
+ * same value. Persists the last returned time on disk to
+ * ensure that time never goes backwards. As a result, the
+ * resulting value can be used to check if a message is the 
+ * "most recent" value and replays of older messages (from
+ * the same origin) would be discarded.
+ * 
+ * @param cfg configuration, used to determine where to 
+ *   store the time; user can also insist RTC is working
+ *   nicely and disable the feature
+ * @return monotonically increasing time
+ */
+struct GNUNET_TIME_Absolute
+GNUNET_TIME_absolute_get_monotonic (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  static const struct GNUNET_CONFIGURATION_Handle *last_cfg;
+  static struct GNUNET_TIME_Absolute last_time;
+  static struct GNUNET_DISK_MapHandle *map_handle;
+  static struct GNUNET_TIME_AbsoluteNBO *map;
+  struct GNUNET_TIME_Absolute now;
+
+  now = GNUNET_TIME_absolute_get ();
+  if (last_cfg != cfg)
+  {
+    char *filename;
+
+    if (NULL != map_handle)
+    {
+      GNUNET_DISK_file_unmap (map_handle);
+      map_handle = NULL;
+    }
+    map = NULL;
+    
+    last_cfg = cfg;
+    if ( (NULL != cfg) &&
+        (GNUNET_OK ==
+         GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                                  "util",
+                                                  "MONOTONIC_TIME_FILENAME",
+                                                  &filename)) )
+    {
+      struct GNUNET_DISK_FileHandle *fh;
+
+      fh = GNUNET_DISK_file_open (filename,
+                                 GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE,
+                                 GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_WRITE |
+                                 GNUNET_DISK_PERM_USER_READ  | GNUNET_DISK_PERM_GROUP_READ);
+      if (NULL == fh)
+      {
+       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                   _("Failed to map `%s', cannot assure monotonic time!\n"),
+                   filename);
+      }
+      else
+      {        
+       off_t size;
+
+       size = 0;
+       GNUNET_break (GNUNET_OK ==
+                     GNUNET_DISK_file_handle_size (fh,
+                                                   &size));
+       if (size < sizeof (*map))
+       {
+         struct GNUNET_TIME_AbsoluteNBO o;
+
+         o = GNUNET_TIME_absolute_hton (now);
+         if (sizeof (o) !=
+             GNUNET_DISK_file_write (fh,
+                                     &o,
+                                     sizeof (o)))
+           size = 0;
+         else
+           size = sizeof (o);
+       }
+       if (size == sizeof (*map))
+       {
+         map = GNUNET_DISK_file_map (fh,
+                                     &map_handle,
+                                     GNUNET_DISK_MAP_TYPE_READWRITE,
+                                     sizeof (*map));
+         if (NULL == map)
+           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                       _("Failed to map `%s', cannot assure monotonic time!\n"),
+                       filename);
+       }
+       else
+       {
+         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                     _("Failed to setup monotonic time file `%s', cannot assure monotonic time!\n"),
+                     filename);
+       }
+      }
+      GNUNET_DISK_file_close (fh);
+      GNUNET_free (filename);
+    }
+  }
+  if (NULL != map)
+    last_time = GNUNET_TIME_absolute_max (GNUNET_TIME_absolute_ntoh (*map),
+                                         last_time);
+  if (now.abs_value_us <= last_time.abs_value_us)
+    now.abs_value_us = last_time.abs_value_us+1;
+  last_time = now;
+  if (NULL != map)
+    *map = GNUNET_TIME_absolute_hton (now);
+  return now;
+}
+
 
+/**
+ * Destructor
+ */
+void __attribute__ ((destructor))
+GNUNET_util_time_fini ()
+{
+  (void) GNUNET_TIME_absolute_get_monotonic (NULL);
+}
 
 /* end of time.c */