1 /**
2  * @file ntp.c  NTP Routines
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #ifdef HAVE_SYS_TIME_H
7 #include <sys/time.h>
8 #else
9 #include <time.h>
10 #endif
11 #include <re_types.h>
12 #include <re_fmt.h>
13 #include <re_list.h>
14 #include <re_sa.h>
15 #include <re_rtp.h>
16 #include "rtcp.h"
17 
18 
19 /*
20  * Unix time:  seconds relative to 0h January 1, 1970
21  * NTP time:   seconds relative to 0h UTC on 1 January 1900
22  */
23 
24 
25 /* Number of seconds from 1900 to 1970 */
26 #define UNIX_NTP_OFFSET 0x83aa7e80
27 
28 
29 /**
30  * Convert from Unix time to NTP time
31  *
32  * @param ntp NTP time to convert to (output)
33  * @param tv  Unix time to convert from (input)
34  */
unix2ntp(struct ntp_time * ntp,const struct timeval * tv)35 void unix2ntp(struct ntp_time *ntp, const struct timeval *tv)
36 {
37 	ntp->hi = (uint32_t)(tv->tv_sec + UNIX_NTP_OFFSET);
38 	ntp->lo = (uint32_t)((double)tv->tv_usec*(double)(1LL<<32)*1.0e-6);
39 }
40 
41 
42 /**
43  * Convert from NTP time to Unix time
44  *
45  * @param tv  Unix time to convert to (output)
46  * @param ntp NTP time to convert from (input)
47  */
ntp2unix(struct timeval * tv,const struct ntp_time * ntp)48 void ntp2unix(struct timeval *tv, const struct ntp_time *ntp)
49 {
50 	tv->tv_sec  = ntp->hi - UNIX_NTP_OFFSET;
51 	tv->tv_usec = (uint32_t)(1.0e6 * (double) ntp->lo / (1LL<<32));
52 }
53 
54 
ntp_time_get(struct ntp_time * ntp)55 int ntp_time_get(struct ntp_time *ntp)
56 {
57 	struct timeval tv;
58 #ifdef WIN32
59 	union {
60 		long long ns100;
61 		FILETIME ft;
62 	} now;
63 
64 	GetSystemTimeAsFileTime(&now.ft);
65 	tv.tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL);
66 	tv.tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL);
67 #else
68 	if (gettimeofday(&tv, NULL) != 0)
69 		return errno;
70 #endif
71 	unix2ntp(ntp, &tv);
72 
73 	return 0;
74 }
75 
76 
77 /**
78  * Convert NTP time to middle 32-bits (compact representation)
79  *
80  * @param ntp NTP time
81  *
82  * @return NTP time in compact representation
83  */
ntp_compact(const struct ntp_time * ntp)84 uint32_t ntp_compact(const struct ntp_time *ntp)
85 {
86 	return ntp ? ((ntp->hi & 0xffff) << 16 | (ntp->lo >> 16)) : 0;
87 }
88 
89 
90 /**
91  * Convert NTP compact representation to microseconds
92  *
93  * @param ntpc  NTP time in compact representation
94  *
95  * @return NTP time in microseconds
96  */
ntp_compact2us(uint32_t ntpc)97 uint64_t ntp_compact2us(uint32_t ntpc)
98 {
99 	const uint32_t hi = (ntpc >> 16) & 0xffff;
100 	const uint32_t lo = (ntpc & 0xffff) << 16;
101 
102 	return (1000000ULL * hi) + ((1000000ULL * lo) >> 32);
103 }
104