1 #include <time.h>
2 #include <sys/ipc.h>
3 #include <sys/time.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9
10 #include "tvhtime.h"
11 #include "tvheadend.h"
12 #include "config.h"
13
14 #if !ENABLE_ANDROID
15 #include <sys/shm.h>
16 #endif
17
18 /*
19 * NTP processing
20 */
21 #define NTPD_BASE 0x4e545030 /* "NTP0" */
22 #define NTPD_UNIT 2
23
24 #if !ENABLE_ANDROID
25 typedef struct
26 {
27 int mode; /* 0 - if valid set
28 * use values,
29 * clear valid
30 * 1 - if valid set
31 * if count before and after read of values is equal,
32 * use values
33 * clear valid
34 */
35 int count;
36 time_t clockTimeStampSec;
37 int clockTimeStampUSec;
38 time_t receiveTimeStampSec;
39 int receiveTimeStampUSec;
40 int leap;
41 int precision;
42 int nsamples;
43 int valid;
44 int pad[10];
45 } ntp_shm_t;
46
47 static ntp_shm_t *
ntp_shm_init(void)48 ntp_shm_init ( void )
49 {
50 int shmid, unit, mode;
51 static ntp_shm_t *shmptr = NULL;
52
53 if (shmptr != NULL)
54 return shmptr;
55
56 unit = getuid() ? 2 : 0;
57 mode = getuid() ? 0666 : 0600;
58
59 shmid = shmget((key_t)NTPD_BASE + unit, sizeof(ntp_shm_t), IPC_CREAT | mode);
60 if (shmid == -1)
61 return NULL;
62
63 shmptr = shmat(shmid, 0, 0);
64
65 if (shmptr) {
66 memset(shmptr, 0, sizeof(ntp_shm_t));
67 shmptr->mode = 1;
68 shmptr->precision = -1;
69 shmptr->nsamples = 1;
70 }
71
72 return shmptr;
73 }
74 #endif
75
76 /*
77 * Update time
78 */
79 void
tvhtime_update(time_t utc,const char * srcname)80 tvhtime_update ( time_t utc, const char *srcname )
81 {
82 #if !ENABLE_ANDROID
83 struct tm tm;
84 struct timeval tv;
85 ntp_shm_t *ntp_shm;
86 int64_t t1, t2, diff;
87
88 localtime_r(&utc, &tm);
89
90 tvhtrace(LS_TIME, "%s - current time is %04d/%02d/%02d %02d:%02d:%02d",
91 srcname,
92 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
93 tm.tm_hour, tm.tm_min, tm.tm_sec);
94
95 gettimeofday(&tv, NULL);
96
97 /* Delta */
98 t1 = utc * 1000000;
99 t2 = tv.tv_sec * 1000000 + tv.tv_usec;
100
101 /* Update local clock */
102 if (config.tvhtime_update_enabled) {
103 if ((diff = llabs(t2 - t1)) > config.tvhtime_tolerance) {
104 #if ENABLE_STIME
105 if (stime(&utc) < 0)
106 tvherror(LS_TIME, "%s - unable to update system time: %s", srcname, strerror(errno));
107 else
108 tvhdebug(LS_TIME, "%s - updated system clock", srcname);
109 #else
110 tvhnotice(LS_TIME, "%s - stime(2) not implemented", srcname);
111 #endif
112 } else {
113 tvhwarn(LS_TIME, "%s - time not updated (diff %"PRId64")", srcname, diff);
114 }
115 }
116
117 /* NTP */
118 if (config.tvhtime_ntp_enabled) {
119 if (!(ntp_shm = ntp_shm_init()))
120 return;
121
122 tvhtrace(LS_TIME, "ntp delta = %"PRId64" us\n", t2 - t1);
123 ntp_shm->valid = 0;
124 ntp_shm->count++;
125 ntp_shm->clockTimeStampSec = utc;
126 ntp_shm->clockTimeStampUSec = 0;
127 ntp_shm->receiveTimeStampSec = tv.tv_sec;
128 ntp_shm->receiveTimeStampUSec = (int)tv.tv_usec;
129 ntp_shm->count++;
130 ntp_shm->valid = 1;
131 }
132 #endif
133 }
134
135 /* Initialise */
tvhtime_init(void)136 void tvhtime_init ( void )
137 {
138 if (config.tvhtime_tolerance == 0)
139 config.tvhtime_tolerance = 5000;
140 }
141