diff options
Diffstat (limited to 'src/util/time.c')
-rw-r--r-- | src/util/time.c | 126 |
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 | */ | ||
777 | struct GNUNET_TIME_Absolute | ||
778 | GNUNET_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 | */ | ||
876 | void __attribute__ ((destructor)) | ||
877 | GNUNET_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 */ |