diff --git a/config.go.example b/config.go.example index 729b411..cce2a2a 100644 --- a/config.go.example +++ b/config.go.example @@ -10,5 +10,6 @@ const ( EnableICMP = true // Time settings + NTPServer = "pool.ntp.org" ActiveTimezone = "UTC" ) diff --git a/main.go b/main.go index 3903237..e3159a9 100644 --- a/main.go +++ b/main.go @@ -109,16 +109,27 @@ func main() { // Extract IP string from the returned NetworkStack ipStr := netStack.localIP.String() - // Sync wall time using public NTP (e.g. Cloudflare: 162.159.200.1 / time.cloudflare.com) - println("Synchronizing clock via NTP...") - oled.ClearBuffer() - tinyfont.WriteLine(oled, defaultFont, 0, 32, "Syncing NTP...", white) - oled.Display() - ntpServer := netip.MustParseAddr("162.159.200.1") - timeOffset, err := syncNTP(netStack, ntpServer, 5*time.Second) - if err != nil { - panicErr("NTP sync failed", err) - } + println("Resolving NTP server:", NTPServer) + oled.ClearBuffer() + tinyfont.WriteLine(oled, defaultFont, 0, 32, "Resolving NTP...", white) + oled.Display() + + ntpServer, err := resolveHostToIP(netStack, NTPServer, 5*time.Second) + if err != nil { + panicErr("NTP DNS lookup failed", err) + } + println("NTP server IP: ", ntpServer.String()) + time.Sleep(1 * time.Second) + + println("Synchronizing clock via NTP...") + oled.ClearBuffer() + tinyfont.WriteLine(oled, defaultFont, 0, 32, "Syncing NTP...", white) + oled.Display() + + timeOffset, err := syncNTP(netStack, ntpServer, 5*time.Second) + if err != nil { + panicErr("NTP sync failed", err) + } println("NTP synced successfully!") oled.ClearBuffer() diff --git a/network.go b/network.go index 7fbc1af..634da82 100644 --- a/network.go +++ b/network.go @@ -225,3 +225,34 @@ func tcpBackoff(consecutiveBackoffs uint) time.Duration { wait := min(shifted, maxWait) return time.Duration(wait) } + +// resolveHostToIP checks if host is already an IP literal, or queries the DNS server. +func resolveHostToIP(stack *NetworkStack, host string, timeout time.Duration) (netip.Addr, error) { + // 1. If it's already an IP string (e.g. "162.159.200.1"), parse and return directly + if ip, err := netip.ParseAddr(host); err == nil { + return ip, nil + } + + // 2. Start asynchronous DNS A-record query + if err := stack.stack.StartLookupIP(host); err != nil { + return netip.Addr{}, fmt.Errorf("start DNS lookup: %w", err) + } + + // 3. Poll ResultLookupIP until done or timed out + deadline := time.Now().Add(timeout) + for time.Now().Before(deadline) { + addrs, done, err := stack.stack.ResultLookupIP(host) + if done { + if err != nil { + return netip.Addr{}, fmt.Errorf("DNS lookup error: %w", err) + } + if len(addrs) == 0 { + return netip.Addr{}, fmt.Errorf("no addresses returned for %s", host) + } + return addrs[0], nil + } + time.Sleep(50 * time.Millisecond) + } + + return netip.Addr{}, fmt.Errorf("DNS lookup timed out for %s", host) +}