James Kuszmaul | 82f6c04 | 2021-01-17 11:30:16 -0800 | [diff] [blame^] | 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 | */ |
| 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 | */ |
| 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 | |
| 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 | */ |
| 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 | */ |
| 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 | } |