1 /*
2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include <osip2/internal.h>
21 #include <osip2/osip_time.h>
22 #include <osipparser2/osip_port.h>
23
24 #ifdef __APPLE__
25 #include <mach/clock.h>
26 #include <mach/mach.h>
27 #endif
28
29 static struct timeval offset = {0, 0};
30
add_gettimeofday(struct timeval * atv,int ms)31 void add_gettimeofday(struct timeval *atv, int ms) {
32 int m;
33
34 if (ms >= 1000000) {
35 atv->tv_usec = 0;
36 m = ms / 1000;
37
38 } else {
39 atv->tv_usec += ms * 1000;
40 m = atv->tv_usec / 1000000;
41 atv->tv_usec = atv->tv_usec % 1000000;
42 }
43
44 atv->tv_sec += m;
45 }
46
min_timercmp(struct timeval * tv1,struct timeval * tv2)47 void min_timercmp(struct timeval *tv1, struct timeval *tv2) {
48 if (tv2->tv_sec == -1)
49 return;
50
51 if (osip_timercmp(tv1, tv2, >)) {
52 /* replace tv1 with tv2 info */
53 tv1->tv_sec = tv2->tv_sec;
54 tv1->tv_usec = tv2->tv_usec;
55 }
56 }
57
58 #if !defined(__PALMOS__) && defined(_WIN32_WCE)
59
60 #include <time.h>
61
osip_gettimeofday(struct timeval * tp,void * tz)62 int osip_gettimeofday(struct timeval *tp, void *tz) {
63 DWORD timemillis = GetTickCount();
64
65 tp->tv_sec = (timemillis / 1000) + offset.tv_sec;
66 tp->tv_usec = (timemillis - (tp->tv_sec * 1000)) * 1000;
67 return 0;
68 }
69
_osip_gettimeofday_realtime(struct timeval * tp,void * tz)70 static int _osip_gettimeofday_realtime(struct timeval *tp, void *tz) {
71 tp->tv_sec = 0;
72 tp->tv_usec = 0;
73 return 0;
74 }
75
time(time_t * t)76 time_t time(time_t *t) {
77 DWORD timemillis = GetTickCount();
78
79 if (timemillis > 0) {
80 if (t != NULL)
81 *t = timemillis / 1000;
82 }
83
84 return timemillis / 1000;
85 }
86
87 #elif !defined(__PALMOS__) && defined(WIN32)
88
89 #include <time.h>
90 #include <sys/timeb.h>
91 #include <windows.h>
92
osip_gettimeofday(struct timeval * tp,void * tz)93 int osip_gettimeofday(struct timeval *tp, void *tz) {
94 struct _timeb timebuffer;
95
96 _ftime(&timebuffer);
97 tp->tv_sec = (long) timebuffer.time + offset.tv_sec;
98 tp->tv_usec = timebuffer.millitm * 1000;
99 return 0;
100 }
101
_osip_gettimeofday_realtime(struct timeval * tp,void * tz)102 static int _osip_gettimeofday_realtime(struct timeval *tp, void *tz) {
103 FILETIME lSystemTimeAsFileTime;
104 LONGLONG ll_now;
105
106 GetSystemTimeAsFileTime(&lSystemTimeAsFileTime);
107 ll_now = (LONGLONG) lSystemTimeAsFileTime.dwLowDateTime + ((LONGLONG)(lSystemTimeAsFileTime.dwHighDateTime) << 32LL);
108 ll_now = ll_now / 10; /* in us */
109 tp->tv_sec = (long) ll_now / 1000000;
110 tp->tv_usec = (long) ll_now % 1000000;
111 return 0;
112 }
113
114 #elif defined(__linux) || defined(__linux__) || defined(HAVE_CLOCK_GETTIME_MONOTONIC)
115
osip_gettimeofday(struct timeval * tp,void * tz)116 int osip_gettimeofday(struct timeval *tp, void *tz) {
117 struct timespec ts;
118
119 if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
120 gettimeofday(tp, tz);
121 return 0;
122 }
123
124 tp->tv_sec = ts.tv_sec + offset.tv_sec;
125 tp->tv_usec = ts.tv_nsec / 1000;
126 return 0;
127 }
128
_osip_gettimeofday_realtime(struct timeval * tp,void * tz)129 static int _osip_gettimeofday_realtime(struct timeval *tp, void *tz) {
130 struct timespec ts;
131
132 if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
133 gettimeofday(tp, tz);
134 return 0;
135 }
136
137 tp->tv_sec = ts.tv_sec;
138 tp->tv_usec = ts.tv_nsec / 1000;
139 return 0;
140 }
141
142 #elif defined(__APPLE__)
143
osip_gettimeofday(struct timeval * tp,void * tz)144 int osip_gettimeofday(struct timeval *tp, void *tz) {
145 clock_serv_t cclock;
146 mach_timespec_t mts;
147
148 host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
149 clock_get_time(cclock, &mts);
150 mach_port_deallocate(mach_task_self(), cclock);
151 tp->tv_sec = mts.tv_sec + offset.tv_sec;
152 tp->tv_usec = mts.tv_nsec / 1000;
153 return 0;
154 }
155
_osip_gettimeofday_realtime(struct timeval * tp,void * tz)156 static int _osip_gettimeofday_realtime(struct timeval *tp, void *tz) {
157 /* TODO */
158 tp->tv_sec = 0;
159 tp->tv_usec = 0;
160 return 0;
161 }
162
163 #else
164
165 /* Should never be compiled: missing monotonic clock */
osip_gettimeofday(struct timeval * tp,void * tz)166 int osip_gettimeofday(struct timeval *tp, void *tz) {
167 gettimeofday(tp, tz);
168 tp->tv_sec += offset.tv_sec;
169 return 0;
170 }
171
_osip_gettimeofday_realtime(struct timeval * tp,void * tz)172 static int _osip_gettimeofday_realtime(struct timeval *tp, void *tz) {
173 tp->tv_sec = 0;
174 tp->tv_usec = 0;
175 return 0;
176 }
177
178 #endif
179
180 #if defined(__arc__)
181
time(time_t * t)182 time_t time(time_t *t) {
183 struct timeval now;
184
185 osip_gettimeofday(&now, NULL);
186
187 if (t != NULL) {
188 *t = now.tv_sec;
189 }
190
191 return now.tv_sec;
192 }
193
194 #endif
195
osip_compensatetime()196 void osip_compensatetime() {
197 #ifndef ANDROID
198 return;
199 #else
200 static struct timeval last_now_monotonic = {0, 0};
201 static struct timeval last_now_real = {0, 0};
202 struct timeval now_monotonic;
203 struct timeval now_real;
204 struct timeval diff_monotonic;
205 struct timeval diff_real;
206
207 _osip_gettimeofday_realtime(&now_real, NULL);
208 osip_gettimeofday(&now_monotonic, NULL);
209 now_monotonic.tv_sec -= offset.tv_sec;
210
211 if (now_real.tv_sec == 0)
212 return; /* no compensation */
213
214 /* monotonic clock may doesn't include deep sleep time */
215 /* the goal is to compensate that time by looking at the real time */
216
217 /* initial call: initialize */
218 if (last_now_monotonic.tv_sec == 0) {
219 _osip_gettimeofday_realtime(&last_now_real, NULL);
220 osip_gettimeofday(&last_now_monotonic, NULL);
221 last_now_monotonic.tv_sec -= offset.tv_sec;
222
223 return;
224 }
225
226 diff_monotonic.tv_sec = now_monotonic.tv_sec - last_now_monotonic.tv_sec;
227 diff_real.tv_sec = now_real.tv_sec - last_now_real.tv_sec;
228
229 if (diff_real.tv_sec < 5)
230 return; /* skip any "back in time" operation or small interval */
231
232 if (diff_real.tv_sec > 3600)
233 return;
234
235 if (diff_real.tv_sec < diff_monotonic.tv_sec + 2)
236 return; /* only large gap needs to be taken into accounts for this program... */
237
238 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL, "adjusting exosip monotonic time (%i)!\n", diff_real.tv_sec - diff_monotonic.tv_sec));
239 offset.tv_sec += diff_real.tv_sec - diff_monotonic.tv_sec;
240
241 /* reset for later use */
242 _osip_gettimeofday_realtime(&last_now_real, NULL);
243 osip_gettimeofday(&last_now_monotonic, NULL);
244 last_now_monotonic.tv_sec -= offset.tv_sec;
245 #endif
246 }
247
osip_getsystemtime(time_t * t)248 time_t osip_getsystemtime(time_t *t) {
249 struct timeval now_monotonic;
250
251 #ifdef ANDROID
252 osip_compensatetime();
253 #endif
254
255 osip_gettimeofday(&now_monotonic, NULL);
256
257 if (t != NULL) {
258 *t = now_monotonic.tv_sec;
259 }
260
261 return now_monotonic.tv_sec;
262 }
263