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