Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync with NTP server #180

Open
psxc2k24 opened this issue Oct 14, 2024 · 0 comments
Open

Sync with NTP server #180

psxc2k24 opened this issue Oct 14, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@psxc2k24
Copy link

On occation the datetime in BIOS is wrong, resulting in things like certificates to be invalid (like when you try to download a new version of OSDCloud). This could be easily remedied by syncing to a nearby NTP-server.
I've added my own little pre-script to address this issue a while back, assuming something similar would appear in the project, but it doesn't look like it.. Anyhoo, it would probably benefit some, so I've added my code below. The main part is stolen from a different project and I've just meshed together to fit the parts I need.

`
if (-not ([System.Management.Automation.PSTypeName]'Time.NTP').Type) {
Add-Type @"
// Code shamelessly pilfered from the Kurumi project
// https://github.com/o5k/kurumi
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;

namespace Time {
public class NTP {
public static DateTime TryGetNetworkTime(string ntpServer) {
if (ntpServer.Length <= 1) {
ntpServer = "pool.ntp.org";
}
int tries = 10;
while (tries-- > 0) {
try {
return GetNetworkTime(ntpServer);
} catch { }
}
throw new Exception("Failed to connect to NTP-server");
}

    public static DateTime GetNetworkTime(string ntpServer) {
        if (ntpServer.Length <= 1) {
            ntpServer = "pool.ntp.org";
        }
        byte[] ntpData = new byte[48];
        ntpData[0] = 0x1B;
        IPAddress[] addresses = Dns.GetHostEntry(ntpServer).AddressList;
        IPEndPoint ipEndPoint = new IPEndPoint(addresses[0], 123);

        using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) {
            socket.Connect(ipEndPoint);
            socket.ReceiveTimeout = 3000;
            socket.Send(ntpData);
            socket.Receive(ntpData);
            socket.Close();
        }

        const byte serverReplyTime = 40;
        
        ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);
        ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);
        
        intPart = SwapEndianness(intPart);
        fractPart = SwapEndianness(fractPart);

        ulong milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
        DateTime networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);

        return networkDateTime.ToLocalTime();
    }
    
    static uint SwapEndianness(ulong x) {
        return (uint)(((x & 0x000000ff) << 24) +
                       ((x & 0x0000ff00) << 8) +
                       ((x & 0x00ff0000) >> 8) +
                       ((x & 0xff000000) >> 24));
    }

    [DllImport("kernel32.dll")]
    public static extern bool SetSystemTime(ref SYSTEMTIME time);

    [StructLayout(LayoutKind.Sequential)]
    public struct SYSTEMTIME {
        public ushort Year;
        public ushort Month;
        public ushort DayOfWeek;
        public ushort Day;
        public ushort Hour;
        public ushort Minute;
        public ushort Second;
        public ushort Milliseconds;

        public SYSTEMTIME(DateTime dt) {
            Year = (ushort)dt.Year;
            Month = (ushort)dt.Month;
            DayOfWeek = (ushort)dt.DayOfWeek;
            Day = (ushort)dt.Day;
            Hour = (ushort)dt.Hour;
            Minute = (ushort)dt.Minute;
            Second = (ushort)dt.Second;
            Milliseconds = (ushort)dt.Millisecond;
        }
    }
    public static DateTime FixTime(string ntpServer) {
        if (ntpServer.Length <= 1) {
            ntpServer = "pool.ntp.org";
        }
        DateTime net = DateTime.Now;
        DateTime self = DateTime.Now;
        TimeSpan offset;
        net = NTP.TryGetNetworkTime(ntpServer);
        offset = self - net;

        DateTime target = DateTime.UtcNow;
        target = target.Subtract(offset);

        NTP.SYSTEMTIME systime = new NTP.SYSTEMTIME(target);
        NTP.SetSystemTime(ref systime);
        return DateTime.Now;
    }
}

}
"@
}

try {
$null = [Time.NTP]::FixTime("time.windows.com")
}
catch {
Write-Host -ForegroundColor Red "Failed to adjust datetime."
}
Write-Host -ForegroundColor Yellow "Today's date: $(([System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId([DateTime]::Now,"W. Europe Standard Time")).GetDateTimeFormats()[8])"
`

@gwblok gwblok added the enhancement New feature or request label Oct 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants