From bdb3420bc937f0ab9187695a56f0e63d7c227f00 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 13 Dec 2018 17:30:08 +0100 Subject: add function to obtain monotonic time --- src/include/gnunet_time_lib.h | 31 ++++- .../gnunet_transport_communication_service.h | 39 ++++++- src/util/disk.c | 6 +- src/util/gnunet-service-resolver.c | 1 - src/util/test_regex.c | 2 +- src/util/test_time.c | 25 +++- src/util/test_tun.c | 2 +- src/util/time.c | 126 ++++++++++++++++++++- 8 files changed, 220 insertions(+), 12 deletions(-) diff --git a/src/include/gnunet_time_lib.h b/src/include/gnunet_time_lib.h index c7a06ba23..674a95534 100644 --- a/src/include/gnunet_time_lib.h +++ b/src/include/gnunet_time_lib.h @@ -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 diff --git a/src/include/gnunet_transport_communication_service.h b/src/include/gnunet_transport_communication_service.h index f81ee6d9a..8cf275660 100644 --- a/src/include/gnunet_transport_communication_service.h +++ b/src/include/gnunet_transport_communication_service.h @@ -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 diff --git a/src/util/disk.c b/src/util/disk.c index dc38d1137..d723303d8 100644 --- a/src/util/disk.c +++ b/src/util/disk.c @@ -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) { diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c index 065a224eb..5f8957d8c 100644 --- a/src/util/gnunet-service-resolver.c +++ b/src/util/gnunet-service-resolver.c @@ -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) { diff --git a/src/util/test_regex.c b/src/util/test_regex.c index 2e7d52828..4eb7cf87d 100644 --- a/src/util/test_regex.c +++ b/src/util/test_regex.c @@ -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). diff --git a/src/util/test_time.c b/src/util/test_time.c index 2ac93e01d..80c4e5337 100644 --- a/src/util/test_time.c +++ b/src/util/test_time.c @@ -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; } diff --git a/src/util/test_tun.c b/src/util/test_tun.c index edbd4c05d..429678fd5 100644 --- a/src/util/test_tun.c +++ b/src/util/test_tun.c @@ -22,7 +22,7 @@ * @author Christian Grothoff */ #include "platform.h" -#include "gnunet_tun_lib.h" +#include "gnunet_util_lib.h" static int ret; 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 @@ /* 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 */ -- cgit v1.2.3