Coverage Report

Created: 2026-09-01 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcoap/src/coap_time.c
Line
Count
Source
1
/* coap_time.c -- Clock Handling
2
 *
3
 * Copyright (C) 2015,2023-2026 Olaf Bergmann <bergmann@tzi.org>
4
 *
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 *
7
 * This file is part of the CoAP library libcoap. Please see
8
 * README for terms of use.
9
 */
10
11
/**
12
 * @file coap_time.c
13
 * @brief Clock handling functions
14
 */
15
16
#include "coap3/coap_libcoap_build.h"
17
18
#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
19
20
#ifdef HAVE_TIME_H
21
#include <time.h>
22
#endif /* HAVE_TIME_H */
23
24
#ifdef HAVE_SYS_TIME_H
25
#include <sys/time.h>
26
#endif /* HAVE_SYS_TIME_H */
27
28
#ifdef HAVE_UNISTD_H
29
#include <unistd.h>  /* _POSIX_TIMERS */
30
#endif /* HAVE_UNISTD_H */
31
32
#ifdef HAVE_WINSOCK2_H
33
#include <winsock2.h>
34
#include <stdint.h>
35
#endif /* HAVE_WINSOCK2_H */
36
37
static coap_tick_t coap_clock_offset = 0;
38
39
#if _POSIX_TIMERS && !defined(__APPLE__) && !defined(__MINGW32__)
40
/* _POSIX_TIMERS is > 0 when clock_gettime() is available */
41
42
/* Use real-time clock for correct timestamps in coap_log(). */
43
292
#define COAP_CLOCK CLOCK_REALTIME
44
#endif /* _POSIX_TIMERS && ! __APPLE__ && ! __MINGW32__ */
45
46
#if defined(HAVE_WINSOCK2_H) && !defined(__MINGW32__)
47
static int
48
gettimeofday(struct timeval *tp, TIME_ZONE_INFORMATION *tzp) {
49
  (void)tzp;
50
  static const uint64_t s_tUnixEpoch = 116444736000000000Ui64;
51
52
  FILETIME file_time;
53
  ULARGE_INTEGER time;
54
  uint64_t tUsSinceUnicEpoch;
55
56
  GetSystemTimeAsFileTime(&file_time);
57
  time.LowPart = file_time.dwLowDateTime;
58
  time.HighPart = file_time.dwHighDateTime;
59
  tUsSinceUnicEpoch = (time.QuadPart - s_tUnixEpoch) / 10;
60
61
  tp->tv_sec = (long)(tUsSinceUnicEpoch / 1000000);
62
  tp->tv_usec = (long)(tUsSinceUnicEpoch % 1000000);
63
  return 0;
64
}
65
#endif /* HAVE_WINSOCK2_H && !__MINGW32__ */
66
67
void
68
34
coap_clock_init(void) {
69
34
#ifdef COAP_CLOCK
70
34
  struct timespec tv;
71
34
  clock_gettime(COAP_CLOCK, &tv);
72
#else /* _POSIX_TIMERS */
73
  struct timeval tv;
74
  gettimeofday(&tv, NULL);
75
#endif /* not _POSIX_TIMERS */
76
77
34
  coap_clock_offset = tv.tv_sec;
78
34
}
79
80
/* creates a Qx.frac from fval */
81
#define Q(frac,fval) ((1 << (frac)) * (fval))
82
83
/* number of frac bits for sub-seconds */
84
#define FRAC 10
85
86
/* rounds val up and right shifts by frac positions */
87
258
#define SHR_FP(val,frac) (((coap_tick_t)((val) + (1 << ((frac) - 1)))) >> (frac))
88
89
void
90
258
coap_ticks(coap_tick_t *t) {
91
258
  coap_tick_t tmp;
92
93
258
#ifdef COAP_CLOCK
94
258
  struct timespec tv;
95
258
  clock_gettime(COAP_CLOCK, &tv);
96
  /* Possible errors are (see clock_gettime(2)):
97
   *  EFAULT tp points outside the accessible address space.
98
   *  EINVAL The clk_id specified is not supported on this system.
99
   * Both cases should not be possible here.
100
   */
101
102
258
  tmp = SHR_FP(tv.tv_nsec * Q(FRAC, (COAP_TICKS_PER_SECOND/1000000000.0)), FRAC);
103
#else /* _POSIX_TIMERS */
104
  /* Fall back to gettimeofday() */
105
106
  struct timeval tv;
107
  gettimeofday(&tv, NULL);
108
  /* Possible errors are (see gettimeofday(2)):
109
   *  EFAULT One of tv or tz pointed outside the accessible address space.
110
   *  EINVAL Timezone (or something else) is invalid.
111
   * Both cases should not be possible here.
112
   */
113
114
  tmp = SHR_FP(tv.tv_usec * Q(FRAC, (COAP_TICKS_PER_SECOND/1000000.0)), FRAC);
115
#endif /* not _POSIX_TIMERS */
116
117
  /* Finally, convert temporary FP representation to multiple of
118
   * COAP_TICKS_PER_SECOND */
119
258
  *t = tmp + (tv.tv_sec - coap_clock_offset) * COAP_TICKS_PER_SECOND;
120
258
}
121
122
coap_time_t
123
0
coap_ticks_to_rt(coap_tick_t t) {
124
0
  return coap_clock_offset + (t / COAP_TICKS_PER_SECOND);
125
0
}
126
127
uint64_t
128
34
coap_ticks_to_rt_us(coap_tick_t t) {
129
34
  return (uint64_t)coap_clock_offset * 1000000 + (uint64_t)t * 1000000 / COAP_TICKS_PER_SECOND;
130
34
}
131
132
coap_tick_t
133
0
coap_ticks_from_rt_us(uint64_t t) {
134
0
  return (coap_tick_t)((t - (uint64_t)coap_clock_offset * 1000000) * COAP_TICKS_PER_SECOND / 1000000);
135
0
}
136
137
#undef Q
138
#undef FRAC
139
#undef SHR_FP
140
141
#else /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
142
143
#ifdef __clang__
144
/* Make compilers happy that do not like empty modules. As this function is
145
 * never used, we ignore -Wunused-function at the end of compiling this file
146
 */
147
#pragma GCC diagnostic ignored "-Wunused-function"
148
#endif
149
COAP_STATIC_INLINE void
150
dummy(void) {
151
}
152
153
#endif /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */