116 lines
3.4 KiB
Factor
116 lines
3.4 KiB
Factor
! Copyright (C) 2010 John Benediktsson
|
|
! See http://factorcode.org/license.txt for BSD license
|
|
|
|
USING: accessors arrays calendar combinators destructors
|
|
fry formatting kernel io io.sockets math pack random
|
|
sequences ;
|
|
|
|
IN: ntp
|
|
|
|
<PRIVATE
|
|
|
|
CONSTANT: REQUEST B{ 0x1b 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 0 0 }
|
|
|
|
: (time) ( sequence -- timestamp )
|
|
[ first ] [ second 32 2^ / ] bi + seconds
|
|
1900 1 1 0 0 0 instant <timestamp> time+ ;
|
|
|
|
: (leap) ( leap -- string/f )
|
|
{
|
|
{ 0 [ "no warning" ] }
|
|
{ 1 [ "last minute has 61 seconds" ] }
|
|
{ 2 [ "last minute has 59 seconds" ] }
|
|
{ 3 [ "alarm condition (clock not synchronized)" ] }
|
|
[ drop f ]
|
|
} case ;
|
|
|
|
: (mode) ( mode -- string )
|
|
{
|
|
{ 0 [ "unspecified" ] }
|
|
{ 1 [ "symmetric active" ] }
|
|
{ 2 [ "symmetric passive" ] }
|
|
{ 3 [ "client" ] }
|
|
{ 4 [ "server" ] }
|
|
{ 5 [ "broadcast" ] }
|
|
{ 6 [ "reserved for NTP control message" ] }
|
|
{ 7 [ "reserved for private use" ] }
|
|
[ drop f ]
|
|
} case ;
|
|
|
|
: (stratum) ( stratum -- string )
|
|
{
|
|
{ 0 [ "unspecified or unavailable" ] }
|
|
{ 1 [ "primary reference (e.g., radio clock)" ] }
|
|
[
|
|
[ 1 > ] [ 255 < ] bi and
|
|
[ "secondary reference (via NTP or SNTP)" ]
|
|
[ "invalid stratum" throw ] if
|
|
]
|
|
} case ;
|
|
|
|
: (ref-id) ( ref-id stratum -- string )
|
|
[
|
|
{
|
|
[ -24 shift 0xff bitand ]
|
|
[ -16 shift 0xff bitand ]
|
|
[ -8 shift 0xff bitand ]
|
|
[ 0xff bitand ]
|
|
} cleave
|
|
] dip {
|
|
{ 0 [ "%c%c%c%c" sprintf ] }
|
|
{ 1 [ "%c%c%c%c" sprintf ] }
|
|
[
|
|
[ 1 > ] [ 255 < ] bi and
|
|
[ "%d.%d.%d.%d" sprintf ]
|
|
[ "invalid stratum" throw ] if
|
|
]
|
|
} case ;
|
|
|
|
TUPLE: ntp leap version mode stratum poll precision
|
|
root-delay root-dispersion ref-id ref-timestamp
|
|
orig-timestamp recv-timestamp tx-timestamp ;
|
|
|
|
: (ntp) ( payload -- ntp )
|
|
"CCCcIIIIIIIIIII" unpack-be {
|
|
[ first -6 shift 0x3 bitand ] ! leap
|
|
[ first -3 shift 0x7 bitand ] ! version
|
|
[ first 0x7 bitand ] ! mode
|
|
[ second ] ! stratum
|
|
[ third ] ! poll
|
|
[ [ 3 ] dip nth ] ! precision
|
|
[ [ 4 ] dip nth 16 2^ / ] ! root-delay
|
|
[ [ 5 ] dip nth 16 2^ / ] ! root-dispersion
|
|
[ [ 6 ] dip nth ] ! ref-id
|
|
[ [ { 7 8 } ] dip nths (time) ] ! ref-timestamp
|
|
[ [ { 9 10 } ] dip nths (time) ] ! orig-timestamp
|
|
[ [ { 11 12 } ] dip nths (time) ] ! recv-timestamp
|
|
[ [ { 13 14 } ] dip nths (time) ] ! tx-timestamp
|
|
} cleave ntp boa
|
|
dup stratum>> '[ _ (ref-id) ] change-ref-id
|
|
[ dup (leap) 2array ] change-leap
|
|
[ dup (mode) 2array ] change-mode
|
|
[ dup (stratum) 2array ] change-stratum ;
|
|
|
|
PRIVATE>
|
|
|
|
! TODO:
|
|
! - socket timeout?
|
|
! - format request properly?
|
|
! - strftime should format millis?
|
|
! - why does <inet4> resolve-host not work?
|
|
|
|
: <ntp> ( host -- ntp )
|
|
123 <inet> resolve-host
|
|
[ inet4? ] filter random [
|
|
[ REQUEST ] 2dip [ send ] [ receive drop ] bi (ntp)
|
|
] with-any-port-local-datagram ;
|
|
|
|
: default-ntp ( -- ntp )
|
|
"pool.ntp.org" <ntp> ;
|
|
|
|
: local-ntp ( -- ntp )
|
|
"localhost" <ntp> ;
|