summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2018-10-25 13:47:13 +0200
committerDaiki Ueno <dueno@redhat.com>2018-10-26 08:23:05 +0200
commita248c0ec45f0ce6ffe349d0fc865fd536033f73f (patch)
tree71029ec915f7a0cbde25ba2d779c01de93d4fab2
parent0ec886fab57ce96394b98f794ed2a96ae9782f6e (diff)
downloadgnutls-a248c0ec45f0ce6ffe349d0fc865fd536033f73f.tar.gz
system: provide a means to replace gettime implementation
While gettime() is extensively used in the code, the library previously hadn't provided a way to replace it for testing. This adds a new internal function _gnutls_global_set_gettime_function and makes use of it through virt-time.h. Signed-off-by: Daiki Ueno <dueno@redhat.com>
-rw-r--r--lib/buffers.c8
-rw-r--r--lib/dtls.c8
-rw-r--r--lib/dtls.h2
-rw-r--r--lib/ext/heartbeat.c8
-rw-r--r--lib/handshake.c2
-rw-r--r--lib/handshake.h2
-rw-r--r--lib/libgnutls.map2
-rw-r--r--lib/nettle/rnd.c2
-rw-r--r--lib/system.c22
-rw-r--r--lib/system.h19
-rw-r--r--tests/virt-time.h27
11 files changed, 66 insertions, 36 deletions
diff --git a/lib/buffers.c b/lib/buffers.c
index cee0d5fc59..78fe6e22cc 100644
--- a/lib/buffers.c
+++ b/lib/buffers.c
@@ -252,7 +252,7 @@ _gnutls_dgram_read(gnutls_session_t session, mbuffer_st ** bufel,
ret = _gnutls_io_check_recv(session, *ms);
if (ret < 0)
return gnutls_assert_val(ret);
- gettime(&t1);
+ gnutls_gettime(&t1);
}
*bufel = _mbuffer_alloc_align16(max_size, get_total_headers(session));
@@ -287,7 +287,7 @@ _gnutls_dgram_read(gnutls_session_t session, mbuffer_st ** bufel,
}
if (ms && *ms > 0) {
- gettime(&t2);
+ gnutls_gettime(&t2);
diff = timespec_sub_ms(&t2, &t1);
if (diff < *ms)
*ms -= diff;
@@ -338,7 +338,7 @@ _gnutls_stream_read(gnutls_session_t session, mbuffer_st ** bufel,
goto cleanup;
}
- gettime(&t1);
+ gnutls_gettime(&t1);
}
reset_errno(session);
@@ -383,7 +383,7 @@ _gnutls_stream_read(gnutls_session_t session, mbuffer_st ** bufel,
(*bufel)->msg.size += i;
if (ms && *ms > 0 && *ms != GNUTLS_INDEFINITE_TIMEOUT) {
- gettime(&t2);
+ gnutls_gettime(&t2);
diff = timespec_sub_ms(&t2, &t1);
if (diff < *ms)
*ms -= diff;
diff --git a/lib/dtls.c b/lib/dtls.c
index 07c3495a46..a22379ece1 100644
--- a/lib/dtls.c
+++ b/lib/dtls.c
@@ -234,7 +234,7 @@ int _dtls_transmit(gnutls_session_t session)
unsigned int diff;
struct timespec now;
- gettime(&now);
+ gnutls_gettime(&now);
/* If we have already sent a flight and we are operating in a
* non blocking way, check if it is time to retransmit or just
@@ -321,7 +321,7 @@ int _dtls_transmit(gnutls_session_t session)
last_type = cur->htype;
}
- gettime(&session->internals.dtls.last_retransmit);
+ gnutls_gettime(&session->internals.dtls.last_retransmit);
if (session->internals.dtls.flight_init == 0) {
session->internals.dtls.flight_init = 1;
@@ -391,7 +391,7 @@ int _dtls_transmit(gnutls_session_t session)
}
keep_up:
- gettime(&now);
+ gnutls_gettime(&now);
} while (ret == GNUTLS_E_TIMEDOUT);
if (ret < 0) {
@@ -789,7 +789,7 @@ unsigned int gnutls_dtls_get_timeout(gnutls_session_t session)
struct timespec now;
unsigned int diff;
- gettime(&now);
+ gnutls_gettime(&now);
diff =
timespec_sub_ms(&now,
diff --git a/lib/dtls.h b/lib/dtls.h
index c7e72cf9b7..717d3bdc6d 100644
--- a/lib/dtls.h
+++ b/lib/dtls.h
@@ -40,7 +40,7 @@ void _dtls_reset_window(struct record_parameters_st *rp);
#define RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, r) { \
struct timespec _now; \
unsigned int _diff; \
- gettime(&_now); \
+ gnutls_gettime(&_now); \
\
_diff = timespec_sub_ms(&_now, &session->internals.handshake_start_time); \
if (_diff > session->internals.handshake_timeout_ms) \
diff --git a/lib/ext/heartbeat.c b/lib/ext/heartbeat.c
index 1b970fbc46..7ec26a9804 100644
--- a/lib/ext/heartbeat.c
+++ b/lib/ext/heartbeat.c
@@ -202,7 +202,7 @@ gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size,
if (ret < 0)
return gnutls_assert_val(ret);
- gettime(&session->internals.hb_ping_start);
+ gnutls_gettime(&session->internals.hb_ping_start);
session->internals.hb_local_data.length = data_size;
session->internals.hb_state = SHB_SEND2;
@@ -220,7 +220,7 @@ gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size,
if (ret < 0)
return gnutls_assert_val(ret);
- gettime(&session->internals.hb_ping_sent);
+ gnutls_gettime(&session->internals.hb_ping_sent);
if (!(flags & GNUTLS_HEARTBEAT_WAIT)) {
session->internals.hb_state = SHB_SEND1;
@@ -246,7 +246,7 @@ gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size,
return gnutls_assert_val(ret);
}
- gettime(&now);
+ gnutls_gettime(&now);
diff =
timespec_sub_ms(&now,
&session->internals.
@@ -405,7 +405,7 @@ unsigned int gnutls_heartbeat_get_timeout(gnutls_session_t session)
struct timespec now;
unsigned int diff;
- gettime(&now);
+ gnutls_gettime(&now);
diff = timespec_sub_ms(&now, &session->internals.hb_ping_sent);
if (diff >= session->internals.hb_actual_retrans_timeout_ms)
return 0;
diff --git a/lib/handshake.c b/lib/handshake.c
index 841c88385d..a20c7a302a 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -2679,7 +2679,7 @@ int gnutls_handshake(gnutls_session_t session)
session->internals.hsk_flags = 0;
session->internals.handshake_in_progress = 1;
session->internals.vc_status = -1;
- gettime(&session->internals.handshake_start_time);
+ gnutls_gettime(&session->internals.handshake_start_time);
if (session->internals.handshake_timeout_ms &&
session->internals.handshake_endtime == 0)
session->internals.handshake_endtime = session->internals.handshake_start_time.tv_sec +
diff --git a/lib/handshake.h b/lib/handshake.h
index 38ef848784..ee5ee7a437 100644
--- a/lib/handshake.h
+++ b/lib/handshake.h
@@ -116,7 +116,7 @@ inline static int handshake_remaining_time(gnutls_session_t session)
{
if (session->internals.handshake_endtime) {
struct timespec now;
- gettime(&now);
+ gnutls_gettime(&now);
if (now.tv_sec < session->internals.handshake_endtime)
return (session->internals.handshake_endtime -
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 041fda7b80..ad6613b907 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1326,4 +1326,6 @@ GNUTLS_PRIVATE_3_4 {
_gnutls_server_name_set_raw;
# Internal symbols needed by tests/suite/resume-with-stek-expiration
_gnutls_set_session_ticket_key_rotation_callback;
+ # Internal symbols needed by tests/virt-time.h
+ _gnutls_global_set_gettime_function;
} GNUTLS_3_4;
diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c
index 9d8b250012..3f816d43ae 100644
--- a/lib/nettle/rnd.c
+++ b/lib/nettle/rnd.c
@@ -106,7 +106,7 @@ static int single_prng_init(struct prng_ctx_st *ctx,
ctx->forkid = _gnutls_get_forkid();
- gettime(&now);
+ gnutls_gettime(&now);
memcpy(nonce, &now, MIN(sizeof(nonce), sizeof(now)));
ctx->last_reseed = now.tv_sec;
}
diff --git a/lib/system.c b/lib/system.c
index 1a17974d58..1bbbf79c84 100644
--- a/lib/system.c
+++ b/lib/system.c
@@ -44,6 +44,26 @@ static HMODULE Crypt32_dll;
/* System specific function wrappers for certificate stores.
*/
gnutls_time_func gnutls_time;
+gnutls_gettime_func gnutls_gettime;
+
+/* emulate gnulib's gettime using gettimeofday to avoid linking to
+ * librt */
+static void _gnutls_gettime(struct timespec *t)
+{
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
+ clock_gettime(CLOCK_REALTIME, t);
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ t->tv_sec = tv.tv_sec;
+ t->tv_nsec = tv.tv_usec * 1000;
+#endif
+}
+
+void _gnutls_global_set_gettime_function(gnutls_gettime_func gettime_func)
+{
+ gnutls_gettime = gettime_func;
+}
int gnutls_system_global_init(void)
{
@@ -66,6 +86,7 @@ int gnutls_system_global_init(void)
Crypt32_dll = crypto;
#endif
gnutls_time = time;
+ gnutls_gettime = _gnutls_gettime;
return 0;
}
@@ -75,6 +96,7 @@ void gnutls_system_global_deinit(void)
FreeLibrary(Crypt32_dll);
#endif
gnutls_time = time;
+ gnutls_gettime = _gnutls_gettime;
}
diff --git a/lib/system.h b/lib/system.h
index 0ae3c63b17..6a948f858d 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -77,7 +77,10 @@ ssize_t system_read(gnutls_transport_ptr_t ptr, void *data,
# define HAVE_NO_LOCKS
#endif
+typedef void (*gnutls_gettime_func) (struct timespec *);
+
extern gnutls_time_func gnutls_time;
+extern gnutls_gettime_func gnutls_gettime;
static inline void millisleep(unsigned int ms)
{
@@ -93,26 +96,14 @@ static inline void millisleep(unsigned int ms)
#endif
}
-/* emulate gnulib's gettime using gettimeofday to avoid linking to
- * librt */
-inline static void gettime(struct timespec *t)
-{
-#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
- clock_gettime(CLOCK_REALTIME, t);
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- t->tv_sec = tv.tv_sec;
- t->tv_nsec = tv.tv_usec * 1000;
-#endif
-}
-
int _gnutls_find_config_path(char *path, size_t max_size);
int _gnutls_ucs2_to_utf8(const void *data, size_t size,
gnutls_datum_t * output, unsigned bigendian);
int _gnutls_utf8_to_ucs2(const void *data, size_t size,
gnutls_datum_t * output);
+void _gnutls_global_set_gettime_function(gnutls_gettime_func gettime_func);
+
int gnutls_system_global_init(void);
void gnutls_system_global_deinit(void);
diff --git a/tests/virt-time.h b/tests/virt-time.h
index 02c8cdb147..0dd35df299 100644
--- a/tests/virt-time.h
+++ b/tests/virt-time.h
@@ -29,19 +29,28 @@
#include <time.h>
#include <gnutls/gnutls.h>
+/* copied from ../lib/system.h so not to include that header from
+ * every test program */
+typedef void (*gnutls_gettime_func) (struct timespec *);
+extern void _gnutls_global_set_gettime_function(gnutls_gettime_func gettime_func);
+
/* virtualize time in a test. This freezes the time in the test, except for
* the advances due to calls to virt_sleep_sec(). This makes the test
- * independent of the test system load, and avoids any long delays.
- *
- * This only affects the parts of the library that utilize gnutls_time(),
- * not the higher precision gettime */
-static time_t _now = 0;
+ * independent of the test system load, and avoids any long delays. */
+static time_t _now;
+static struct timespec _now_ts;
-#define virt_sec_sleep(s) _now += s
+#define virt_sec_sleep(s) { \
+ _now += s; \
+ _now_ts.tv_sec += s; \
+ }
#define virt_time_init() { \
_now = time(0); \
gnutls_global_set_time_function(mytime); \
+ _now_ts.tv_sec = _now; \
+ _now_ts.tv_nsec = 0; \
+ _gnutls_global_set_gettime_function(mygettime); \
}
@@ -53,4 +62,10 @@ static time_t mytime(time_t * t)
return _now;
}
+static void mygettime(struct timespec * t)
+{
+ if (t)
+ *t = _now_ts;
+}
+
#endif