Skip to content

Commit cf67997

Browse files
authored
fix(timesync): ensure that auto-update waits for time sync (#609)
- Added check to not attempt auto update if time sync is needed and not yet successful (delays 30 second to recheck). - Added resync of time when DHCP or link state changes if online - Added conditional* fallback from configured* NTP servers to the IP-named NTP servers, and then to the DNS named ones if that fails - Added conditional* fallback from the configured* HTTP servers to the default DNS named ones. - Uses the configuration* option for how many queries to run in parallel - Added known static IPs for time servers (in case DNS resolution isn't up yet) - Added time.cloudflare.com to fall-back NTP servers - Added fallback to NTP via hostnames - Logs the resultant time (and mode)
1 parent 80a8b9e commit cf67997

File tree

5 files changed

+69
-27
lines changed

5 files changed

+69
-27
lines changed

internal/network/netif.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ type NetworkInterfaceOptions struct {
4848
DefaultHostname string
4949
OnStateChange func(state *NetworkInterfaceState)
5050
OnInitialCheck func(state *NetworkInterfaceState)
51-
OnDhcpLeaseChange func(lease *udhcpc.Lease)
51+
OnDhcpLeaseChange func(lease *udhcpc.Lease, state *NetworkInterfaceState)
5252
OnConfigChange func(config *NetworkConfig)
5353
NetworkConfig *NetworkConfig
5454
}
@@ -94,7 +94,7 @@ func NewNetworkInterfaceState(opts *NetworkInterfaceOptions) (*NetworkInterfaceS
9494
_ = s.updateNtpServersFromLease(lease)
9595
_ = s.setHostnameIfNotSame()
9696

97-
opts.OnDhcpLeaseChange(lease)
97+
opts.OnDhcpLeaseChange(lease, s)
9898
},
9999
})
100100

internal/timesync/ntp.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,32 @@ import (
99
"github.com/beevik/ntp"
1010
)
1111

12-
var defaultNTPServers = []string{
12+
var defaultNTPServerIPs = []string{
13+
// These servers are known by static IP and as such don't need DNS lookups
14+
// These are from Google and Cloudflare since if they're down, the internet
15+
// is broken anyway
16+
"162.159.200.1", // time.cloudflare.com IPv4
17+
"162.159.200.123", // time.cloudflare.com IPv4
18+
"2606:4700:f1::1", // time.cloudflare.com IPv6
19+
"2606:4700:f1::123", // time.cloudflare.com IPv6
20+
"216.239.35.0", // time.google.com IPv4
21+
"216.239.35.4", // time.google.com IPv4
22+
"216.239.35.8", // time.google.com IPv4
23+
"216.239.35.12", // time.google.com IPv4
24+
"2001:4860:4806::", // time.google.com IPv6
25+
"2001:4860:4806:4::", // time.google.com IPv6
26+
"2001:4860:4806:8::", // time.google.com IPv6
27+
"2001:4860:4806:c::", // time.google.com IPv6
28+
}
29+
30+
var defaultNTPServerHostnames = []string{
31+
// should use something from https://github.com/jauderho/public-ntp-servers
1332
"time.apple.com",
1433
"time.aws.com",
1534
"time.windows.com",
1635
"time.google.com",
17-
"162.159.200.123", // time.cloudflare.com IPv4
18-
"2606:4700:f1::123", // time.cloudflare.com IPv6
19-
"0.pool.ntp.org",
20-
"1.pool.ntp.org",
21-
"2.pool.ntp.org",
22-
"3.pool.ntp.org",
36+
"time.cloudflare.com",
37+
"pool.ntp.org",
2338
}
2439

2540
func (t *TimeSync) queryNetworkTime(ntpServers []string) (now *time.Time, offset *time.Duration) {

internal/timesync/timesync.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ func (t *TimeSync) Sync() error {
158158
var (
159159
now *time.Time
160160
offset *time.Duration
161+
log zerolog.Logger
161162
)
162163

163164
metricTimeSyncCount.Inc()
@@ -166,54 +167,54 @@ func (t *TimeSync) Sync() error {
166167

167168
Orders:
168169
for _, mode := range syncMode.Ordering {
170+
log = t.l.With().Str("mode", mode).Logger()
169171
switch mode {
170172
case "ntp_user_provided":
171173
if syncMode.Ntp {
172-
t.l.Info().Msg("using NTP custom servers")
174+
log.Info().Msg("using NTP custom servers")
173175
now, offset = t.queryNetworkTime(t.networkConfig.TimeSyncNTPServers)
174176
if now != nil {
175-
t.l.Info().Str("source", "NTP").Time("now", *now).Msg("time obtained")
176177
break Orders
177178
}
178179
}
179180
case "ntp_dhcp":
180181
if syncMode.Ntp {
181-
t.l.Info().Msg("using NTP servers from DHCP")
182+
log.Info().Msg("using NTP servers from DHCP")
182183
now, offset = t.queryNetworkTime(t.dhcpNtpAddresses)
183184
if now != nil {
184-
t.l.Info().Str("source", "NTP DHCP").Time("now", *now).Msg("time obtained")
185185
break Orders
186186
}
187187
}
188188
case "ntp":
189189
if syncMode.Ntp && syncMode.NtpUseFallback {
190-
t.l.Info().Msg("using NTP fallback")
191-
now, offset = t.queryNetworkTime(defaultNTPServers)
190+
log.Info().Msg("using NTP fallback IPs")
191+
now, offset = t.queryNetworkTime(defaultNTPServerIPs)
192+
if now == nil {
193+
log.Info().Msg("using NTP fallback hostnames")
194+
now, offset = t.queryNetworkTime(defaultNTPServerHostnames)
195+
}
192196
if now != nil {
193-
t.l.Info().Str("source", "NTP fallback").Time("now", *now).Msg("time obtained")
194197
break Orders
195198
}
196199
}
197200
case "http_user_provided":
198201
if syncMode.Http {
199-
t.l.Info().Msg("using HTTP custom URLs")
202+
log.Info().Msg("using HTTP custom URLs")
200203
now = t.queryAllHttpTime(t.networkConfig.TimeSyncHTTPUrls)
201204
if now != nil {
202-
t.l.Info().Str("source", "HTTP").Time("now", *now).Msg("time obtained")
203205
break Orders
204206
}
205207
}
206208
case "http":
207209
if syncMode.Http && syncMode.HttpUseFallback {
208-
t.l.Info().Msg("using HTTP fallback")
210+
log.Info().Msg("using HTTP fallback")
209211
now = t.queryAllHttpTime(defaultHTTPUrls)
210212
if now != nil {
211-
t.l.Info().Str("source", "HTTP fallback").Time("now", *now).Msg("time obtained")
212213
break Orders
213214
}
214215
}
215216
default:
216-
t.l.Warn().Str("mode", mode).Msg("unknown time sync mode, skipping")
217+
log.Warn().Msg("unknown time sync mode, skipping")
217218
}
218219
}
219220

@@ -226,6 +227,8 @@ Orders:
226227
now = &newNow
227228
}
228229

230+
log.Info().Time("now", *now).Msg("time obtained")
231+
229232
err := t.setSystemTime(*now)
230233
if err != nil {
231234
return fmt.Errorf("failed to set system time: %w", err)

main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,25 @@ func Main() {
9696
if !config.AutoUpdateEnabled {
9797
return
9898
}
99+
100+
if isTimeSyncNeeded() || !timeSync.IsSyncSuccess() {
101+
logger.Debug().Msg("system time is not synced, will retry in 30 seconds")
102+
time.Sleep(30 * time.Second)
103+
continue
104+
}
105+
99106
if currentSession != nil {
100107
logger.Debug().Msg("skipping update since a session is active")
101108
time.Sleep(1 * time.Minute)
102109
continue
103110
}
111+
104112
includePreRelease := config.IncludePreRelease
105113
err = TryUpdate(context.Background(), GetDeviceID(), includePreRelease)
106114
if err != nil {
107115
logger.Warn().Err(err).Msg("failed to auto update")
108116
}
117+
109118
time.Sleep(1 * time.Hour)
110119
}
111120
}()

network.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var (
1515
networkState *network.NetworkInterfaceState
1616
)
1717

18-
func networkStateChanged() {
18+
func networkStateChanged(isOnline bool) {
1919
// do not block the main thread
2020
go waitCtrlAndRequestDisplayUpdate(true)
2121

@@ -37,6 +37,13 @@ func networkStateChanged() {
3737
networkState.GetFQDN(),
3838
}, true)
3939
}
40+
41+
// if the network is now online, trigger an NTP sync if still needed
42+
if isOnline && timeSync != nil && (isTimeSyncNeeded() || !timeSync.IsSyncSuccess()) {
43+
if err := timeSync.Sync(); err != nil {
44+
logger.Warn().Str("error", err.Error()).Msg("unable to sync time on network state change")
45+
}
46+
}
4047
}
4148

4249
func initNetwork() error {
@@ -48,13 +55,13 @@ func initNetwork() error {
4855
NetworkConfig: config.NetworkConfig,
4956
Logger: networkLogger,
5057
OnStateChange: func(state *network.NetworkInterfaceState) {
51-
networkStateChanged()
58+
networkStateChanged(state.IsOnline())
5259
},
5360
OnInitialCheck: func(state *network.NetworkInterfaceState) {
54-
networkStateChanged()
61+
networkStateChanged(state.IsOnline())
5562
},
56-
OnDhcpLeaseChange: func(lease *udhcpc.Lease) {
57-
networkStateChanged()
63+
OnDhcpLeaseChange: func(lease *udhcpc.Lease, state *network.NetworkInterfaceState) {
64+
networkStateChanged(state.IsOnline())
5865

5966
if currentSession == nil {
6067
return
@@ -64,7 +71,15 @@ func initNetwork() error {
6471
},
6572
OnConfigChange: func(networkConfig *network.NetworkConfig) {
6673
config.NetworkConfig = networkConfig
67-
networkStateChanged()
74+
networkStateChanged(false)
75+
76+
if mDNS != nil {
77+
_ = mDNS.SetListenOptions(networkConfig.GetMDNSMode())
78+
_ = mDNS.SetLocalNames([]string{
79+
networkState.GetHostname(),
80+
networkState.GetFQDN(),
81+
}, true)
82+
}
6883
},
6984
})
7085

0 commit comments

Comments
 (0)