13 people like it.

Async SNTP client

An asynchronous SNTP client that can retrieve the current time from an internet time server (such as time-a.nist.gov) and optionally update the local system clock to match. Demonstrates async UDP communication, bit-shifting, and native interop/PInvoke.

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
141: 
142: 
143: 
144: 
145: 
146: 
147: 
148: 
149: 
150: 
151: 
152: 
153: 
154: 
155: 
156: 
157: 
158: 
159: 
160: 
161: 
162: 
163: 
164: 
165: 
166: 
167: 
168: 
169: 
170: 
171: 
172: 
173: 
174: 
175: 
176: 
177: 
178: 
179: 
180: 
181: 
182: 
183: 
184: 
185: 
186: 
187: 
188: 
189: 
190: 
191: 
192: 
193: 
194: 
195: 
196: 
197: 
198: 
199: 
200: 
201: 
202: 
203: 
204: 
205: 
206: 
207: 
208: 
209: 
210: 
211: 
212: 
213: 
214: 
215: 
216: 
217: 
218: 
219: 
220: 
221: 
222: 
223: 
224: 
225: 
226: 
227: 
228: 
229: 
230: 
231: 
232: 
233: 
234: 
235: 
236: 
237: 
238: 
239: 
240: 
241: 
242: 
243: 
244: 
245: 
246: 
247: 
248: 
249: 
250: 
251: 
252: 
253: 
254: 
255: 
256: 
257: 
258: 
259: 
260: 
261: 
262: 
263: 
264: 
265: 
266: 
267: 
268: 
269: 
270: 
271: 
272: 
273: 
274: 
#nowarn "51"

module private Interop =
    open System
    open System.Runtime.InteropServices

    /// SYSTEMTIME structure used by SetLocalTime
    [<Struct>]
    type SYSTEMTIME =
        val year: int16
        val month: int16
        val dayOfWeek: int16
        val day: int16
        val hour: int16
        val minute: int16
        val second: int16
        val ms: int16
        new (time:DateTime) = {
            year      = int16 time.Year
            month     = int16 time.Month
            dayOfWeek = int16 time.DayOfWeek
            day       = int16 time.Day
            hour      = int16 time.Hour
            minute    = int16 time.Minute
            second    = int16 time.Second
            ms        = int16 time.Millisecond
        }
 
    [<DllImport("kernel32.dll")>]
    extern void SetLocalTime(SYSTEMTIME* t)

    let setSystemTime (time:DateTime) =
        let mutable st = SYSTEMTIME(time)
        SetLocalTime(&&st)

module NtpClient =

    // based on code from http://www.codeproject.com/KB/IP/ntpclient.aspx

    open System
    open System.Net
    open System.Net.Sockets

    type System.Net.Sockets.UdpClient with
        member x.AsyncSend (bytes: byte[]) =
            Async.FromBeginEnd((fun (ar, s) -> x.BeginSend(bytes, bytes.Length, ar, s)), x.EndSend)

        member x.AsyncReceive (endPoint: IPEndPoint ref) =
            Async.FromBeginEnd(x.BeginReceive, fun ar -> x.EndReceive(ar, endPoint))

    /// Leap year indicator
    type LeapIndicator =
        /// 0 - No warning
        | NoWarning
        /// 1 - Last minute has 61 seconds
        | LastMinute61
        /// 2 - Last minute has 59 seconds
        | LastMinute59
        /// 3 - Alarm condition (clock not synchronized)
        | Alarm

    type Mode =
        | SymmetricActive
        | SymmetricPassive
        | Client
        | Server
        | Broadcast
        | Unknown

    type Stratum =
        | Unspecified
        | PrimaryReference
        | SecondaryReference
        | Reserved

    // NTP data structure length
    let [<Literal>] private ntpDataLength = 48
    // offset constants for timestamps in the data structure
    let [<Literal>] offRefID  = 12
    let [<Literal>] offRefTS  = 16
    let [<Literal>] offOrigTS = 24
    let [<Literal>] offRcvTS  = 32
    let [<Literal>] offTrnTS  = 40
    let epoch = DateTime(1900, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)

    /// Initialize a data array with a client request and the current timestamp.
    let initData () =
        let ms = uint64 (DateTime.UtcNow - epoch).TotalMilliseconds
        let intpart = ms / 1000UL
        let fractpart = (((ms % 1000UL) * 0x100000000UL) / 1000UL)
        Array.init ntpDataLength
            (function
             | 0 -> 0x1Buy // Set version number to 4 and Mode to 3 (client)
             | x when x = offTrnTS + 0 -> byte (intpart >>> 24)
             | x when x = offTrnTS + 1 -> byte (intpart >>> 16)
             | x when x = offTrnTS + 2 -> byte (intpart >>> 08)
             | x when x = offTrnTS + 3 -> byte intpart
             | x when x = offTrnTS + 4 -> byte (fractpart >>> 24)
             | x when x = offTrnTS + 5 -> byte (fractpart >>> 16)
             | x when x = offTrnTS + 6 -> byte (fractpart >>> 08)
             | x when x = offTrnTS + 7 -> byte fractpart
             | _ -> 0uy)


    type NtpInfo(data: byte[]) =

        let creationTime = DateTime.Now
        
        /// Compute the date, given the offset of a 8-byte array
        let computeDate offset =
            let intpart =
                (uint64 data.[offset + 0] <<< 24) |||
                (uint64 data.[offset + 1] <<< 16) |||
                (uint64 data.[offset + 2] <<< 08) |||
                (uint64 data.[offset + 3])
            let fractpart =
                (uint64 data.[offset + 4] <<< 24) |||
                (uint64 data.[offset + 5] <<< 16) |||
                (uint64 data.[offset + 6] <<< 08) |||
                (uint64 data.[offset + 7])
            let ms = intpart * 1000UL + (fractpart * 1000UL) / 0x100000000UL
            let elapsed = TimeSpan.FromMilliseconds(float ms)
            epoch + elapsed
    
        member x.LeapIndicator =
            // Isolate the two most significant bits
            match data.[0] >>> 6 with
            | 0uy -> NoWarning
            | 1uy -> LastMinute61
            | 2uy -> LastMinute59
            | _   -> Alarm

        member x.VersionNumber =
            // isolate bits 3-5
            (data.[0] &&& 0x38uy) >>> 3

        member x.Mode =
            // Isolate bits 0-3
            match data.[0] &&& 0x7uy with
            | 1uy -> SymmetricActive
            | 2uy -> SymmetricPassive
            | 3uy -> Client
            | 4uy -> Server
            | 5uy -> Broadcast
            | _   -> Unknown

        member x.Stratum =
            match data.[1] with
            | 0uy              -> Unspecified
            | 1uy              -> PrimaryReference
            | x when x <= 15uy -> SecondaryReference
            | _                -> Reserved

        member x.PollInterval =
            pown (uint32 data.[2]) 2

        /// Precision (in milliseconds)
        member x.Precision =
            (pown (uint32 data.[3]) 2) * 1000u

        /// Root Delay (in milliseconds)
        member x.RootDelay =
            let temp =
                uint32 data.[4] <<< 24 |||
                uint32 data.[5] <<< 16 |||
                uint32 data.[6] <<< 08 |||
                uint32 data.[7]
            1000.0 * (float temp / 0x10000LF)

        /// Root Dispersion (in milliseconds)
        member x.RootDispersion =
            let temp =
                uint32 data.[8]  <<< 24 |||
                uint32 data.[9]  <<< 16 |||
                uint32 data.[10] <<< 08 |||
                uint32 data.[11]
            1000.0 * (float temp / 0x10000LF)

        member x.ReferenceId =
            match x.Stratum with
            | PrimaryReference | Unspecified ->
                String([| char data.[offRefID + 0]
                          char data.[offRefID + 1]
                          char data.[offRefID + 2]
                          char data.[offRefID + 3] |])
            | SecondaryReference ->
                match x.VersionNumber with
                | 3uy -> // Version 3, Reference ID is an IPv4 address
                    let address = 
                        IPAddress([| data.[offRefID + 0]
                                     data.[offRefID + 1]
                                     data.[offRefID + 2]
                                     data.[offRefID + 3] |])
                    try
                        let host = Dns.GetHostEntry(address)
                        sprintf "%s (%O)" host.HostName address
                    with _ ->
                        address.ToString()
                | 4uy -> // Version 4, Reference ID is the timestamp of last update
                    let time = computeDate offRefID
                    // take care of time zone
                    let offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)
                    (time + offset).ToString()
                | _ -> "N/A"
            | Reserved -> "N/A"

        member x.ReferenceTimestamp =
            let time = computeDate offRefTS
            let offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)
            time + offset

        member x.OriginateTimestamp =
            let time = computeDate offOrigTS
            let offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)
            time + offset

        member x.ReceiveTimestamp =
            let time = computeDate offRcvTS
            let offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)
            time + offset

        member x.TransmitTimestamp =
            let time = computeDate offTrnTS
            let offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)
            time + offset

        member x.ReceptionTimestamp =
            creationTime

        /// Round trip delay (in milliseconds)
        member x.RoundTripDelay =
            let delay = (x.ReceiveTimestamp - x.OriginateTimestamp) + (x.ReceptionTimestamp - x.TransmitTimestamp)
            int delay.TotalMilliseconds

        /// Local clock offset (in milliseconds)
        member x.LocalClockOffset =
            let offset = (x.ReceiveTimestamp - x.OriginateTimestamp) - (x.ReceptionTimestamp - x.TransmitTimestamp)
            int (offset.TotalMilliseconds / 2.0)

        override x.ToString() =
            sprintf "%A" x

    
    let query server = 
        async {
            let! hosts = Async.FromBeginEnd(server, Dns.BeginGetHostAddresses, Dns.EndGetHostAddresses)
            if hosts = null || hosts.Length = 0 then
                failwithf "Could not resolve IP address for host '%s'." server

            let endPoint = IPEndPoint(hosts.[0], 123)
            use timeSocket = new UdpClient()
            timeSocket.Connect endPoint
            let sentData = initData()
            let! sentBytes = timeSocket.AsyncSend(sentData)
            let! rcvData = timeSocket.AsyncReceive(ref endPoint)
            timeSocket.Close()
            let info = NtpInfo(rcvData)
            if rcvData.Length <> ntpDataLength || info.Mode <> Server then
                failwithf "Invalid response from %s." server

            return info
        }

    let queryAsTask =
        query >> Async.StartAsTask
        
    let updateClock server =
        async {
            let! timeInfo = query server
            // add half the round-trip delay to the server time
            let targetTime = timeInfo.TransmitTimestamp + TimeSpan.FromMilliseconds(float timeInfo.RoundTripDelay / 2.0)
            Interop.setSystemTime targetTime
            printfn "Set local time to %A." targetTime
        } |> Async.RunSynchronously
namespace System
namespace System.Runtime
namespace System.Runtime.InteropServices
Multiple items
type StructAttribute =
  inherit Attribute
  new : unit -> StructAttribute

Full name: Microsoft.FSharp.Core.StructAttribute

--------------------
new : unit -> StructAttribute
Multiple items
type private SYSTEMTIME =
  struct
    new : time:DateTime -> SYSTEMTIME
    val year: int16
    val month: int16
    val dayOfWeek: int16
    val day: int16
    val hour: int16
    val minute: int16
    val second: int16
    val ms: int16
  end

Full name: Script.Interop.SYSTEMTIME


 SYSTEMTIME structure used by SetLocalTime


--------------------
SYSTEMTIME()
private new : time:DateTime -> SYSTEMTIME
SYSTEMTIME.year: int16
Multiple items
val int16 : value:'T -> int16 (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int16

--------------------
type int16 = Int16

Full name: Microsoft.FSharp.Core.int16

--------------------
type int16<'Measure> = int16

Full name: Microsoft.FSharp.Core.int16<_>
SYSTEMTIME.month: int16
SYSTEMTIME.dayOfWeek: int16
SYSTEMTIME.day: int16
SYSTEMTIME.hour: int16
SYSTEMTIME.minute: int16
SYSTEMTIME.second: int16
SYSTEMTIME.ms: int16
val time : DateTime
Multiple items
type DateTime =
  struct
    new : ticks:int64 -> DateTime + 10 overloads
    member Add : value:TimeSpan -> DateTime
    member AddDays : value:float -> DateTime
    member AddHours : value:float -> DateTime
    member AddMilliseconds : value:float -> DateTime
    member AddMinutes : value:float -> DateTime
    member AddMonths : months:int -> DateTime
    member AddSeconds : value:float -> DateTime
    member AddTicks : value:int64 -> DateTime
    member AddYears : value:int -> DateTime
    ...
  end

Full name: System.DateTime

--------------------
DateTime()
   (+0 other overloads)
DateTime(ticks: int64) : unit
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
   (+0 other overloads)
property DateTime.Year: int
property DateTime.Month: int
property DateTime.DayOfWeek: DayOfWeek
property DateTime.Day: int
property DateTime.Hour: int
property DateTime.Minute: int
property DateTime.Second: int
property DateTime.Millisecond: int
Multiple items
type DllImportAttribute =
  inherit Attribute
  new : dllName:string -> DllImportAttribute
  val EntryPoint : string
  val CharSet : CharSet
  val SetLastError : bool
  val ExactSpelling : bool
  val PreserveSig : bool
  val CallingConvention : CallingConvention
  val BestFitMapping : bool
  val ThrowOnUnmappableChar : bool
  member Value : string

Full name: System.Runtime.InteropServices.DllImportAttribute

--------------------
DllImportAttribute(dllName: string) : unit
val private SetLocalTime : t:nativeptr<SYSTEMTIME> -> unit

Full name: Script.Interop.SetLocalTime
val t : nativeptr<SYSTEMTIME>
val private setSystemTime : time:DateTime -> unit

Full name: Script.Interop.setSystemTime
val mutable st : SYSTEMTIME
module NtpClient

from Script
namespace System.Net
namespace System.Net.Sockets
Multiple items
type UdpClient =
  new : unit -> UdpClient + 5 overloads
  member AllowNatTraversal : allowed:bool -> unit
  member Available : int
  member BeginReceive : requestCallback:AsyncCallback * state:obj -> IAsyncResult
  member BeginSend : datagram:byte[] * bytes:int * requestCallback:AsyncCallback * state:obj -> IAsyncResult + 2 overloads
  member Client : Socket with get, set
  member Close : unit -> unit
  member Connect : endPoint:IPEndPoint -> unit + 2 overloads
  member DontFragment : bool with get, set
  member DropMulticastGroup : multicastAddr:IPAddress -> unit + 1 overload
  ...

Full name: System.Net.Sockets.UdpClient

--------------------
UdpClient() : unit
UdpClient(family: AddressFamily) : unit
UdpClient(port: int) : unit
UdpClient(localEP: IPEndPoint) : unit
UdpClient(port: int, family: AddressFamily) : unit
UdpClient(hostname: string, port: int) : unit
val x : UdpClient
member UdpClient.AsyncSend : bytes:byte [] -> Async<int>

Full name: Script.NtpClient.AsyncSend
val bytes : byte []
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.byte

--------------------
type byte = Byte

Full name: Microsoft.FSharp.Core.byte
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member Async.FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member Async.FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member Async.FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
val ar : AsyncCallback
val s : obj
UdpClient.BeginSend(datagram: byte [], bytes: int, requestCallback: AsyncCallback, state: obj) : IAsyncResult
UdpClient.BeginSend(datagram: byte [], bytes: int, endPoint: IPEndPoint, requestCallback: AsyncCallback, state: obj) : IAsyncResult
UdpClient.BeginSend(datagram: byte [], bytes: int, hostname: string, port: int, requestCallback: AsyncCallback, state: obj) : IAsyncResult
property Array.Length: int
UdpClient.EndSend(asyncResult: IAsyncResult) : int
member UdpClient.AsyncReceive : endPoint:IPEndPoint ref -> Async<byte []>

Full name: Script.NtpClient.AsyncReceive
val endPoint : IPEndPoint ref
Multiple items
type IPEndPoint =
  inherit EndPoint
  new : address:int64 * port:int -> IPEndPoint + 1 overload
  member Address : IPAddress with get, set
  member AddressFamily : AddressFamily
  member Create : socketAddress:SocketAddress -> EndPoint
  member Equals : comparand:obj -> bool
  member GetHashCode : unit -> int
  member Port : int with get, set
  member Serialize : unit -> SocketAddress
  member ToString : unit -> string
  static val MinPort : int
  ...

Full name: System.Net.IPEndPoint

--------------------
IPEndPoint(address: int64, port: int) : unit
IPEndPoint(address: IPAddress, port: int) : unit
Multiple items
val ref : value:'T -> 'T ref

Full name: Microsoft.FSharp.Core.Operators.ref

--------------------
type 'T ref = Ref<'T>

Full name: Microsoft.FSharp.Core.ref<_>
UdpClient.BeginReceive(requestCallback: AsyncCallback, state: obj) : IAsyncResult
val ar : IAsyncResult
UdpClient.EndReceive(asyncResult: IAsyncResult, remoteEP: byref<IPEndPoint>) : byte []
type LeapIndicator =
  | NoWarning
  | LastMinute61
  | LastMinute59
  | Alarm

Full name: Script.NtpClient.LeapIndicator


 Leap year indicator
union case LeapIndicator.NoWarning: LeapIndicator


 0 - No warning
union case LeapIndicator.LastMinute61: LeapIndicator


 1 - Last minute has 61 seconds
union case LeapIndicator.LastMinute59: LeapIndicator


 2 - Last minute has 59 seconds
union case LeapIndicator.Alarm: LeapIndicator


 3 - Alarm condition (clock not synchronized)
type Mode =
  | SymmetricActive
  | SymmetricPassive
  | Client
  | Server
  | Broadcast
  | Unknown

Full name: Script.NtpClient.Mode
union case Mode.SymmetricActive: Mode
union case Mode.SymmetricPassive: Mode
union case Mode.Client: Mode
union case Mode.Server: Mode
union case Mode.Broadcast: Mode
union case Mode.Unknown: Mode
type Stratum =
  | Unspecified
  | PrimaryReference
  | SecondaryReference
  | Reserved

Full name: Script.NtpClient.Stratum
union case Stratum.Unspecified: Stratum
union case Stratum.PrimaryReference: Stratum
union case Stratum.SecondaryReference: Stratum
union case Stratum.Reserved: Stratum
Multiple items
type LiteralAttribute =
  inherit Attribute
  new : unit -> LiteralAttribute

Full name: Microsoft.FSharp.Core.LiteralAttribute

--------------------
new : unit -> LiteralAttribute
val private ntpDataLength : int

Full name: Script.NtpClient.ntpDataLength
val offRefID : int

Full name: Script.NtpClient.offRefID
val offRefTS : int

Full name: Script.NtpClient.offRefTS
val offOrigTS : int

Full name: Script.NtpClient.offOrigTS
val offRcvTS : int

Full name: Script.NtpClient.offRcvTS
val offTrnTS : int

Full name: Script.NtpClient.offTrnTS
val epoch : DateTime

Full name: Script.NtpClient.epoch
type DateTimeKind =
  | Unspecified = 0
  | Utc = 1
  | Local = 2

Full name: System.DateTimeKind
field DateTimeKind.Utc = 1
val initData : unit -> byte []

Full name: Script.NtpClient.initData


 Initialize a data array with a client request and the current timestamp.
val ms : uint64
Multiple items
val uint64 : value:'T -> uint64 (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.uint64

--------------------
type uint64 = UInt64

Full name: Microsoft.FSharp.Core.uint64
property DateTime.UtcNow: DateTime
val intpart : uint64
val fractpart : uint64
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val init : count:int -> initializer:(int -> 'T) -> 'T []

Full name: Microsoft.FSharp.Collections.Array.init
val x : int
Multiple items
type NtpInfo =
  new : data:byte [] -> NtpInfo
  override ToString : unit -> string
  member LeapIndicator : LeapIndicator
  member LocalClockOffset : int
  member Mode : Mode
  member OriginateTimestamp : DateTime
  member PollInterval : uint32
  member Precision : uint32
  member ReceiveTimestamp : DateTime
  member ReceptionTimestamp : DateTime
  ...

Full name: Script.NtpClient.NtpInfo

--------------------
new : data:byte [] -> NtpInfo
val data : byte []
val creationTime : DateTime
property DateTime.Now: DateTime
val computeDate : (int -> DateTime)


 Compute the date, given the offset of a 8-byte array
val offset : int
val elapsed : TimeSpan
Multiple items
type TimeSpan =
  struct
    new : ticks:int64 -> TimeSpan + 3 overloads
    member Add : ts:TimeSpan -> TimeSpan
    member CompareTo : value:obj -> int + 1 overload
    member Days : int
    member Duration : unit -> TimeSpan
    member Equals : value:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member Hours : int
    member Milliseconds : int
    member Minutes : int
    ...
  end

Full name: System.TimeSpan

--------------------
TimeSpan()
TimeSpan(ticks: int64) : unit
TimeSpan(hours: int, minutes: int, seconds: int) : unit
TimeSpan(days: int, hours: int, minutes: int, seconds: int) : unit
TimeSpan(days: int, hours: int, minutes: int, seconds: int, milliseconds: int) : unit
TimeSpan.FromMilliseconds(value: float) : TimeSpan
Multiple items
val float : value:'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------
type float = Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
val x : NtpInfo
Multiple items
member NtpInfo.LeapIndicator : LeapIndicator

Full name: Script.NtpClient.NtpInfo.LeapIndicator

--------------------
type LeapIndicator =
  | NoWarning
  | LastMinute61
  | LastMinute59
  | Alarm

Full name: Script.NtpClient.LeapIndicator


 Leap year indicator
member NtpInfo.VersionNumber : byte

Full name: Script.NtpClient.NtpInfo.VersionNumber
Multiple items
member NtpInfo.Mode : Mode

Full name: Script.NtpClient.NtpInfo.Mode

--------------------
type Mode =
  | SymmetricActive
  | SymmetricPassive
  | Client
  | Server
  | Broadcast
  | Unknown

Full name: Script.NtpClient.Mode
Multiple items
member NtpInfo.Stratum : Stratum

Full name: Script.NtpClient.NtpInfo.Stratum

--------------------
type Stratum =
  | Unspecified
  | PrimaryReference
  | SecondaryReference
  | Reserved

Full name: Script.NtpClient.Stratum
val x : byte
member NtpInfo.PollInterval : uint32

Full name: Script.NtpClient.NtpInfo.PollInterval
val pown : x:'T -> n:int -> 'T (requires member get_One and member ( * ) and member ( / ))

Full name: Microsoft.FSharp.Core.Operators.pown
Multiple items
val uint32 : value:'T -> uint32 (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.uint32

--------------------
type uint32 = UInt32

Full name: Microsoft.FSharp.Core.uint32
member NtpInfo.Precision : uint32

Full name: Script.NtpClient.NtpInfo.Precision


 Precision (in milliseconds)
member NtpInfo.RootDelay : float

Full name: Script.NtpClient.NtpInfo.RootDelay


 Root Delay (in milliseconds)
val temp : uint32
member NtpInfo.RootDispersion : float

Full name: Script.NtpClient.NtpInfo.RootDispersion


 Root Dispersion (in milliseconds)
member NtpInfo.ReferenceId : String

Full name: Script.NtpClient.NtpInfo.ReferenceId
property NtpInfo.Stratum: Stratum
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
Multiple items
val char : value:'T -> char (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.char

--------------------
type char = Char

Full name: Microsoft.FSharp.Core.char
property NtpInfo.VersionNumber: byte
val address : IPAddress
Multiple items
type IPAddress =
  new : newAddress:int64 -> IPAddress + 2 overloads
  member Address : int64 with get, set
  member AddressFamily : AddressFamily
  member Equals : comparand:obj -> bool
  member GetAddressBytes : unit -> byte[]
  member GetHashCode : unit -> int
  member IsIPv6LinkLocal : bool
  member IsIPv6Multicast : bool
  member IsIPv6SiteLocal : bool
  member IsIPv6Teredo : bool
  ...

Full name: System.Net.IPAddress

--------------------
IPAddress(newAddress: int64) : unit
IPAddress(address: byte []) : unit
IPAddress(address: byte [], scopeid: int64) : unit
val host : IPHostEntry
type Dns =
  static member BeginGetHostAddresses : hostNameOrAddress:string * requestCallback:AsyncCallback * state:obj -> IAsyncResult
  static member BeginGetHostByName : hostName:string * requestCallback:AsyncCallback * stateObject:obj -> IAsyncResult
  static member BeginGetHostEntry : hostNameOrAddress:string * requestCallback:AsyncCallback * stateObject:obj -> IAsyncResult + 1 overload
  static member BeginResolve : hostName:string * requestCallback:AsyncCallback * stateObject:obj -> IAsyncResult
  static member EndGetHostAddresses : asyncResult:IAsyncResult -> IPAddress[]
  static member EndGetHostByName : asyncResult:IAsyncResult -> IPHostEntry
  static member EndGetHostEntry : asyncResult:IAsyncResult -> IPHostEntry
  static member EndResolve : asyncResult:IAsyncResult -> IPHostEntry
  static member GetHostAddresses : hostNameOrAddress:string -> IPAddress[]
  static member GetHostByAddress : address:string -> IPHostEntry + 1 overload
  ...

Full name: System.Net.Dns
Dns.GetHostEntry(address: IPAddress) : IPHostEntry
Dns.GetHostEntry(hostNameOrAddress: string) : IPHostEntry
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
property IPHostEntry.HostName: string
IPAddress.ToString() : string
val offset : TimeSpan
type TimeZone =
  member DaylightName : string
  member GetDaylightChanges : year:int -> DaylightTime
  member GetUtcOffset : time:DateTime -> TimeSpan
  member IsDaylightSavingTime : time:DateTime -> bool
  member StandardName : string
  member ToLocalTime : time:DateTime -> DateTime
  member ToUniversalTime : time:DateTime -> DateTime
  static member CurrentTimeZone : TimeZone
  static member IsDaylightSavingTime : time:DateTime * daylightTimes:DaylightTime -> bool

Full name: System.TimeZone
property TimeZone.CurrentTimeZone: TimeZone
TimeZone.GetUtcOffset(time: DateTime) : TimeSpan
member NtpInfo.ReferenceTimestamp : DateTime

Full name: Script.NtpClient.NtpInfo.ReferenceTimestamp
member NtpInfo.OriginateTimestamp : DateTime

Full name: Script.NtpClient.NtpInfo.OriginateTimestamp
member NtpInfo.ReceiveTimestamp : DateTime

Full name: Script.NtpClient.NtpInfo.ReceiveTimestamp
member NtpInfo.TransmitTimestamp : DateTime

Full name: Script.NtpClient.NtpInfo.TransmitTimestamp
member NtpInfo.ReceptionTimestamp : DateTime

Full name: Script.NtpClient.NtpInfo.ReceptionTimestamp
member NtpInfo.RoundTripDelay : int

Full name: Script.NtpClient.NtpInfo.RoundTripDelay


 Round trip delay (in milliseconds)
val delay : TimeSpan
property NtpInfo.ReceiveTimestamp: DateTime
property NtpInfo.OriginateTimestamp: DateTime
property NtpInfo.ReceptionTimestamp: DateTime
property NtpInfo.TransmitTimestamp: DateTime
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
property TimeSpan.TotalMilliseconds: float
member NtpInfo.LocalClockOffset : int

Full name: Script.NtpClient.NtpInfo.LocalClockOffset


 Local clock offset (in milliseconds)
override NtpInfo.ToString : unit -> string

Full name: Script.NtpClient.NtpInfo.ToString
val query : server:string -> Async<NtpInfo>

Full name: Script.NtpClient.query
val server : string
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val hosts : IPAddress []
Dns.BeginGetHostAddresses(hostNameOrAddress: string, requestCallback: AsyncCallback, state: obj) : IAsyncResult
Dns.EndGetHostAddresses(asyncResult: IAsyncResult) : IPAddress []
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
val endPoint : IPEndPoint
val timeSocket : UdpClient
UdpClient.Connect(endPoint: IPEndPoint) : unit
UdpClient.Connect(addr: IPAddress, port: int) : unit
UdpClient.Connect(hostname: string, port: int) : unit
val sentData : byte []
val sentBytes : int
member UdpClient.AsyncSend : bytes:byte [] -> Async<int>
val rcvData : byte []
member UdpClient.AsyncReceive : endPoint:IPEndPoint ref -> Async<byte []>
UdpClient.Close() : unit
val info : NtpInfo
property NtpInfo.Mode: Mode
val queryAsTask : (string -> Threading.Tasks.Task<NtpInfo>)

Full name: Script.NtpClient.queryAsTask
static member Async.StartAsTask : computation:Async<'T> * ?taskCreationOptions:Threading.Tasks.TaskCreationOptions * ?cancellationToken:Threading.CancellationToken -> Threading.Tasks.Task<'T>
val updateClock : server:string -> unit

Full name: Script.NtpClient.updateClock
val timeInfo : NtpInfo
val targetTime : DateTime
property NtpInfo.RoundTripDelay: int


 Round trip delay (in milliseconds)
module Interop

from Script
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:Threading.CancellationToken -> 'T

More information

Link:http://fssnip.net/4B
Posted:12 years ago
Author:Joel Mueller
Tags: async , udp , sntp , interop , pinvoke , networking