aboutsummaryrefslogtreecommitdiff
path: root/src/util/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/time.c')
-rw-r--r--src/util/time.c126
1 files changed, 123 insertions, 3 deletions
diff --git a/src/util/time.c b/src/util/time.c
index b02c43c1b..46d3a2b65 100644
--- a/src/util/time.c
+++ b/src/util/time.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2001-2013 GNUnet e.V. 3 Copyright (C) 2001-2013, 2018 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -22,8 +22,7 @@
22 * @brief functions for handling time and time arithmetic 22 * @brief functions for handling time and time arithmetic
23 */ 23 */
24#include "platform.h" 24#include "platform.h"
25#include "gnunet_crypto_lib.h" 25#include "gnunet_util_lib.h"
26#include "gnunet_time_lib.h"
27 26
28#define LOG(kind,...) GNUNET_log_from (kind, "util-time", __VA_ARGS__) 27#define LOG(kind,...) GNUNET_log_from (kind, "util-time", __VA_ARGS__)
29 28
@@ -757,6 +756,127 @@ GNUNET_TIME_randomized_backoff(struct GNUNET_TIME_Relative rt, struct GNUNET_TIM
757} 756}
758 757
759 758
759/**
760 * Obtain the current time and make sure it is monotonically
761 * increasing. Guards against systems without an RTC or
762 * clocks running backwards and other nasty surprises. Does
763 * not guarantee that the returned time is near the current
764 * time returned by #GNUNET_TIME_absolute_get(). Two
765 * subsequent calls (within a short time period) may return the
766 * same value. Persists the last returned time on disk to
767 * ensure that time never goes backwards. As a result, the
768 * resulting value can be used to check if a message is the
769 * "most recent" value and replays of older messages (from
770 * the same origin) would be discarded.
771 *
772 * @param cfg configuration, used to determine where to
773 * store the time; user can also insist RTC is working
774 * nicely and disable the feature
775 * @return monotonically increasing time
776 */
777struct GNUNET_TIME_Absolute
778GNUNET_TIME_absolute_get_monotonic (const struct GNUNET_CONFIGURATION_Handle *cfg)
779{
780 static const struct GNUNET_CONFIGURATION_Handle *last_cfg;
781 static struct GNUNET_TIME_Absolute last_time;
782 static struct GNUNET_DISK_MapHandle *map_handle;
783 static struct GNUNET_TIME_AbsoluteNBO *map;
784 struct GNUNET_TIME_Absolute now;
785
786 now = GNUNET_TIME_absolute_get ();
787 if (last_cfg != cfg)
788 {
789 char *filename;
790
791 if (NULL != map_handle)
792 {
793 GNUNET_DISK_file_unmap (map_handle);
794 map_handle = NULL;
795 }
796 map = NULL;
797
798 last_cfg = cfg;
799 if ( (NULL != cfg) &&
800 (GNUNET_OK ==
801 GNUNET_CONFIGURATION_get_value_filename (cfg,
802 "util",
803 "MONOTONIC_TIME_FILENAME",
804 &filename)) )
805 {
806 struct GNUNET_DISK_FileHandle *fh;
807
808 fh = GNUNET_DISK_file_open (filename,
809 GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE,
810 GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_WRITE |
811 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_GROUP_READ);
812 if (NULL == fh)
813 {
814 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
815 _("Failed to map `%s', cannot assure monotonic time!\n"),
816 filename);
817 }
818 else
819 {
820 off_t size;
821
822 size = 0;
823 GNUNET_break (GNUNET_OK ==
824 GNUNET_DISK_file_handle_size (fh,
825 &size));
826 if (size < sizeof (*map))
827 {
828 struct GNUNET_TIME_AbsoluteNBO o;
829
830 o = GNUNET_TIME_absolute_hton (now);
831 if (sizeof (o) !=
832 GNUNET_DISK_file_write (fh,
833 &o,
834 sizeof (o)))
835 size = 0;
836 else
837 size = sizeof (o);
838 }
839 if (size == sizeof (*map))
840 {
841 map = GNUNET_DISK_file_map (fh,
842 &map_handle,
843 GNUNET_DISK_MAP_TYPE_READWRITE,
844 sizeof (*map));
845 if (NULL == map)
846 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
847 _("Failed to map `%s', cannot assure monotonic time!\n"),
848 filename);
849 }
850 else
851 {
852 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
853 _("Failed to setup monotonic time file `%s', cannot assure monotonic time!\n"),
854 filename);
855 }
856 }
857 GNUNET_DISK_file_close (fh);
858 GNUNET_free (filename);
859 }
860 }
861 if (NULL != map)
862 last_time = GNUNET_TIME_absolute_max (GNUNET_TIME_absolute_ntoh (*map),
863 last_time);
864 if (now.abs_value_us <= last_time.abs_value_us)
865 now.abs_value_us = last_time.abs_value_us+1;
866 last_time = now;
867 if (NULL != map)
868 *map = GNUNET_TIME_absolute_hton (now);
869 return now;
870}
871
760 872
873/**
874 * Destructor
875 */
876void __attribute__ ((destructor))
877GNUNET_util_time_fini ()
878{
879 (void) GNUNET_TIME_absolute_get_monotonic (NULL);
880}
761 881
762/* end of time.c */ 882/* end of time.c */