feat: Waku v2 bridge

Issue #12610
This commit is contained in:
Michal Iskierko
2023-11-12 13:29:38 +01:00
parent 56e7bd01ca
commit 6d31343205
6716 changed files with 1982502 additions and 5891 deletions

14
vendor/github.com/beevik/ntp/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,14 @@
language: go
sudo: false
go:
- 1.9.x
- 1.12.x
- tip
matrix:
allow_failures:
- go: tip
script:
- go test -v ./...

7
vendor/github.com/beevik/ntp/CONTRIBUTORS generated vendored Normal file
View File

@@ -0,0 +1,7 @@
Brett Vickers (beevik)
Mikhail Salosin (AlphaB)
Anton Tolchanov (knyar)
Christopher Batey (chbatey)
Meng Zhuo (mengzhuo)
Leonid Evdokimov (darkk)
Ask Bjørn Hansen (abh)

24
vendor/github.com/beevik/ntp/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,24 @@
Copyright 2015-2017 Brett Vickers. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

72
vendor/github.com/beevik/ntp/README.md generated vendored Normal file
View File

@@ -0,0 +1,72 @@
[![Build Status](https://travis-ci.org/beevik/ntp.svg?branch=master)](https://travis-ci.org/beevik/ntp)
[![GoDoc](https://godoc.org/github.com/beevik/ntp?status.svg)](https://godoc.org/github.com/beevik/ntp)
ntp
===
The ntp package is an implementation of a Simple NTP (SNTP) client based on
[RFC5905](https://tools.ietf.org/html/rfc5905). It allows you to connect to
a remote NTP server and request information about the current time.
## Querying the current time
If all you care about is the current time according to a remote NTP server,
simply use the `Time` function:
```go
time, err := ntp.Time("0.beevik-ntp.pool.ntp.org")
```
## Querying time metadata
To obtain the current time as well as some additional metadata about the time,
use the [`Query`](https://godoc.org/github.com/beevik/ntp#Query) function:
```go
response, err := ntp.Query("0.beevik-ntp.pool.ntp.org")
time := time.Now().Add(response.ClockOffset)
```
Alternatively, use the [`QueryWithOptions`](https://godoc.org/github.com/beevik/ntp#QueryWithOptions)
function if you want to change the default behavior used by the `Query`
function:
```go
options := ntp.QueryOptions{ Timeout: 30*time.Second, TTL: 5 }
response, err := ntp.QueryWithOptions("0.beevik-ntp.pool.ntp.org", options)
time := time.Now().Add(response.ClockOffset)
```
The [`Response`](https://godoc.org/github.com/beevik/ntp#Response) structure
returned by `Query` includes the following information:
* `Time`: The time the server transmitted its response, according to its own clock.
* `ClockOffset`: The estimated offset of the local system clock relative to the server's clock. For a more accurate time reading, you may add this offset to any subsequent system clock reading.
* `RTT`: An estimate of the round-trip-time delay between the client and the server.
* `Precision`: The precision of the server's clock reading.
* `Stratum`: The server's stratum, which indicates the number of hops from the server to the reference clock. A stratum 1 server is directly attached to the reference clock. If the stratum is zero, the server has responded with the "kiss of death".
* `ReferenceID`: A unique identifier for the consulted reference clock.
* `ReferenceTime`: The time at which the server last updated its local clock setting.
* `RootDelay`: The server's aggregate round-trip-time delay to the stratum 1 server.
* `RootDispersion`: The server's estimated maximum measurement error relative to the reference clock.
* `RootDistance`: An estimate of the root synchronization distance between the client and the stratum 1 server.
* `Leap`: The leap second indicator, indicating whether a second should be added to or removed from the current month's last minute.
* `MinError`: A lower bound on the clock error between the client and the server.
* `KissCode`: A 4-character string describing the reason for a "kiss of death" response (stratum=0).
* `Poll`: The maximum polling interval between successive messages to the server.
The `Response` structure's [`Validate`](https://godoc.org/github.com/beevik/ntp#Response.Validate)
method performs additional sanity checks to determine whether the response is
suitable for time synchronization purposes.
```go
err := response.Validate()
if err == nil {
// response data is suitable for synchronization purposes
}
```
## Using the NTP pool
The NTP pool is a shared resource used by people all over the world.
To prevent it from becoming overloaded, please avoid querying the standard
`pool.ntp.org` zone names in your applications. Instead, consider requesting
your own [vendor zone](http://www.pool.ntp.org/en/vendors.html) or [joining
the pool](http://www.pool.ntp.org/join.html).

64
vendor/github.com/beevik/ntp/RELEASE_NOTES.md generated vendored Normal file
View File

@@ -0,0 +1,64 @@
Release v0.3.0
==============
There have been no breaking changes or further deprecations since the
previous release.
**Changes**
* Fixed a bug in the calculation of NTP timestamps.
Release v0.2.0
==============
There are no breaking changes or further deprecations in this release.
**Changes**
* Added `KissCode` to the `Response` structure.
Release v0.1.1
==============
**Breaking changes**
* Removed the `MaxStratum` constant.
**Deprecations**
* Officially deprecated the `TimeV` function.
**Internal changes**
* Removed `minDispersion` from the `RootDistance` calculation, since the value
was arbitrary.
* Moved some validation into main code path so that invalid `TransmitTime` and
`mode` responses trigger an error even when `Response.Validate` is not
called.
Release v0.1.0
==============
This is the initial release of the `ntp` package. Currently it supports the following features:
* `Time()` to query the current time according to a remote NTP server.
* `Query()` to query multiple pieces of time-related information from a remote NTP server.
* `QueryWithOptions()`, which is like `Query()` but with the ability to override default query options.
Time-related information returned by the `Query` functions includes:
* `Time`: the time the server transmitted its response, according to the server's clock.
* `ClockOffset`: the estimated offset of the client's clock relative to the server's clock. You may apply this offset to any local system clock reading once the query is complete.
* `RTT`: an estimate of the round-trip-time delay between the client and the server.
* `Precision`: the precision of the server's clock reading.
* `Stratum`: the "stratum" level of the server, where 1 indicates a server directly connected to a reference clock, and values greater than 1 indicating the number of hops from the reference clock.
* `ReferenceID`: A unique identifier for the NTP server that was contacted.
* `ReferenceTime`: The time at which the server last updated its local clock setting.
* `RootDelay`: The server's round-trip delay to the reference clock.
* `RootDispersion`: The server's total dispersion to the referenced clock.
* `RootDistance`: An estimate of the root synchronization distance.
* `Leap`: The leap second indicator.
* `MinError`: A lower bound on the clock error between the client and the server.
* `Poll`: the maximum polling interval between successive messages on the server.
The `Response` structure returned by the `Query` functions also contains a `Response.Validate()` function that returns an error if any of the fields returned by the server are invalid.

573
vendor/github.com/beevik/ntp/ntp.go generated vendored Normal file
View File

@@ -0,0 +1,573 @@
// Copyright 2015-2017 Brett Vickers.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package ntp provides an implementation of a Simple NTP (SNTP) client
// capable of querying the current time from a remote NTP server. See
// RFC5905 (https://tools.ietf.org/html/rfc5905) for more details.
//
// This approach grew out of a go-nuts post by Michael Hofmann:
// https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/FlcdMU5fkLQ
package ntp
import (
"crypto/rand"
"encoding/binary"
"errors"
"fmt"
"net"
"time"
"golang.org/x/net/ipv4"
)
// The LeapIndicator is used to warn if a leap second should be inserted
// or deleted in the last minute of the current month.
type LeapIndicator uint8
const (
// LeapNoWarning indicates no impending leap second.
LeapNoWarning LeapIndicator = 0
// LeapAddSecond indicates the last minute of the day has 61 seconds.
LeapAddSecond = 1
// LeapDelSecond indicates the last minute of the day has 59 seconds.
LeapDelSecond = 2
// LeapNotInSync indicates an unsynchronized leap second.
LeapNotInSync = 3
)
// Internal constants
const (
defaultNtpVersion = 4
nanoPerSec = 1000000000
maxStratum = 16
defaultTimeout = 5 * time.Second
maxPollInterval = (1 << 17) * time.Second
maxDispersion = 16 * time.Second
)
// Internal variables
var (
ntpEpoch = time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)
)
type mode uint8
// NTP modes. This package uses only client mode.
const (
reserved mode = 0 + iota
symmetricActive
symmetricPassive
client
server
broadcast
controlMessage
reservedPrivate
)
// An ntpTime is a 64-bit fixed-point (Q32.32) representation of the number of
// seconds elapsed.
type ntpTime uint64
// Duration interprets the fixed-point ntpTime as a number of elapsed seconds
// and returns the corresponding time.Duration value.
func (t ntpTime) Duration() time.Duration {
sec := (t >> 32) * nanoPerSec
frac := (t & 0xffffffff) * nanoPerSec
nsec := frac >> 32
if uint32(frac) >= 0x80000000 {
nsec++
}
return time.Duration(sec + nsec)
}
// Time interprets the fixed-point ntpTime as an absolute time and returns
// the corresponding time.Time value.
func (t ntpTime) Time() time.Time {
return ntpEpoch.Add(t.Duration())
}
// toNtpTime converts the time.Time value t into its 64-bit fixed-point
// ntpTime representation.
func toNtpTime(t time.Time) ntpTime {
nsec := uint64(t.Sub(ntpEpoch))
sec := nsec / nanoPerSec
nsec = uint64(nsec-sec*nanoPerSec) << 32
frac := uint64(nsec / nanoPerSec)
if nsec%nanoPerSec >= nanoPerSec/2 {
frac++
}
return ntpTime(sec<<32 | frac)
}
// An ntpTimeShort is a 32-bit fixed-point (Q16.16) representation of the
// number of seconds elapsed.
type ntpTimeShort uint32
// Duration interprets the fixed-point ntpTimeShort as a number of elapsed
// seconds and returns the corresponding time.Duration value.
func (t ntpTimeShort) Duration() time.Duration {
sec := uint64(t>>16) * nanoPerSec
frac := uint64(t&0xffff) * nanoPerSec
nsec := frac >> 16
if uint16(frac) >= 0x8000 {
nsec++
}
return time.Duration(sec + nsec)
}
// msg is an internal representation of an NTP packet.
type msg struct {
LiVnMode uint8 // Leap Indicator (2) + Version (3) + Mode (3)
Stratum uint8
Poll int8
Precision int8
RootDelay ntpTimeShort
RootDispersion ntpTimeShort
ReferenceID uint32
ReferenceTime ntpTime
OriginTime ntpTime
ReceiveTime ntpTime
TransmitTime ntpTime
}
// setVersion sets the NTP protocol version on the message.
func (m *msg) setVersion(v int) {
m.LiVnMode = (m.LiVnMode & 0xc7) | uint8(v)<<3
}
// setMode sets the NTP protocol mode on the message.
func (m *msg) setMode(md mode) {
m.LiVnMode = (m.LiVnMode & 0xf8) | uint8(md)
}
// setLeap modifies the leap indicator on the message.
func (m *msg) setLeap(li LeapIndicator) {
m.LiVnMode = (m.LiVnMode & 0x3f) | uint8(li)<<6
}
// getVersion returns the version value in the message.
func (m *msg) getVersion() int {
return int((m.LiVnMode >> 3) & 0x07)
}
// getMode returns the mode value in the message.
func (m *msg) getMode() mode {
return mode(m.LiVnMode & 0x07)
}
// getLeap returns the leap indicator on the message.
func (m *msg) getLeap() LeapIndicator {
return LeapIndicator((m.LiVnMode >> 6) & 0x03)
}
// QueryOptions contains the list of configurable options that may be used
// with the QueryWithOptions function.
type QueryOptions struct {
Timeout time.Duration // defaults to 5 seconds
Version int // NTP protocol version, defaults to 4
LocalAddress string // IP address to use for the client address
Port int // Server port, defaults to 123
TTL int // IP TTL to use, defaults to system default
}
// A Response contains time data, some of which is returned by the NTP server
// and some of which is calculated by the client.
type Response struct {
// Time is the transmit time reported by the server just before it
// responded to the client's NTP query.
Time time.Time
// ClockOffset is the estimated offset of the client clock relative to
// the server. Add this to the client's system clock time to obtain a
// more accurate time.
ClockOffset time.Duration
// RTT is the measured round-trip-time delay estimate between the client
// and the server.
RTT time.Duration
// Precision is the reported precision of the server's clock.
Precision time.Duration
// Stratum is the "stratum level" of the server. The smaller the number,
// the closer the server is to the reference clock. Stratum 1 servers are
// attached directly to the reference clock. A stratum value of 0
// indicates the "kiss of death," which typically occurs when the client
// issues too many requests to the server in a short period of time.
Stratum uint8
// ReferenceID is a 32-bit identifier identifying the server or
// reference clock.
ReferenceID uint32
// ReferenceTime is the time when the server's system clock was last
// set or corrected.
ReferenceTime time.Time
// RootDelay is the server's estimated aggregate round-trip-time delay to
// the stratum 1 server.
RootDelay time.Duration
// RootDispersion is the server's estimated maximum measurement error
// relative to the stratum 1 server.
RootDispersion time.Duration
// RootDistance is an estimate of the total synchronization distance
// between the client and the stratum 1 server.
RootDistance time.Duration
// Leap indicates whether a leap second should be added or removed from
// the current month's last minute.
Leap LeapIndicator
// MinError is a lower bound on the error between the client and server
// clocks. When the client and server are not synchronized to the same
// clock, the reported timestamps may appear to violate the principle of
// causality. In other words, the NTP server's response may indicate
// that a message was received before it was sent. In such cases, the
// minimum error may be useful.
MinError time.Duration
// KissCode is a 4-character string describing the reason for a
// "kiss of death" response (stratum = 0). For a list of standard kiss
// codes, see https://tools.ietf.org/html/rfc5905#section-7.4.
KissCode string
// Poll is the maximum interval between successive NTP polling messages.
// It is not relevant for simple NTP clients like this one.
Poll time.Duration
}
// Validate checks if the response is valid for the purposes of time
// synchronization.
func (r *Response) Validate() error {
// Handle invalid stratum values.
if r.Stratum == 0 {
return fmt.Errorf("kiss of death received: %s", r.KissCode)
}
if r.Stratum >= maxStratum {
return errors.New("invalid stratum in response")
}
// Handle invalid leap second indicator.
if r.Leap == LeapNotInSync {
return errors.New("invalid leap second")
}
// Estimate the "freshness" of the time. If it exceeds the maximum
// polling interval (~36 hours), then it cannot be considered "fresh".
freshness := r.Time.Sub(r.ReferenceTime)
if freshness > maxPollInterval {
return errors.New("server clock not fresh")
}
// Calculate the peer synchronization distance, lambda:
// lambda := RootDelay/2 + RootDispersion
// If this value exceeds MAXDISP (16s), then the time is not suitable
// for synchronization purposes.
// https://tools.ietf.org/html/rfc5905#appendix-A.5.1.1.
lambda := r.RootDelay/2 + r.RootDispersion
if lambda > maxDispersion {
return errors.New("invalid dispersion")
}
// If the server's transmit time is before its reference time, the
// response is invalid.
if r.Time.Before(r.ReferenceTime) {
return errors.New("invalid time reported")
}
// nil means the response is valid.
return nil
}
// Query returns a response from the remote NTP server host. It contains
// the time at which the server transmitted the response as well as other
// useful information about the time and the remote server.
func Query(host string) (*Response, error) {
return QueryWithOptions(host, QueryOptions{})
}
// QueryWithOptions performs the same function as Query but allows for the
// customization of several query options.
func QueryWithOptions(host string, opt QueryOptions) (*Response, error) {
m, now, err := getTime(host, opt)
if err != nil {
return nil, err
}
return parseTime(m, now), nil
}
// TimeV returns the current time using information from a remote NTP server.
// On error, it returns the local system time. The version may be 2, 3, or 4.
//
// Deprecated: TimeV is deprecated. Use QueryWithOptions instead.
func TimeV(host string, version int) (time.Time, error) {
m, recvTime, err := getTime(host, QueryOptions{Version: version})
if err != nil {
return time.Now(), err
}
r := parseTime(m, recvTime)
err = r.Validate()
if err != nil {
return time.Now(), err
}
// Use the clock offset to calculate the time.
return time.Now().Add(r.ClockOffset), nil
}
// Time returns the current time using information from a remote NTP server.
// It uses version 4 of the NTP protocol. On error, it returns the local
// system time.
func Time(host string) (time.Time, error) {
return TimeV(host, defaultNtpVersion)
}
// getTime performs the NTP server query and returns the response message
// along with the local system time it was received.
func getTime(host string, opt QueryOptions) (*msg, ntpTime, error) {
if opt.Version == 0 {
opt.Version = defaultNtpVersion
}
if opt.Version < 2 || opt.Version > 4 {
return nil, 0, errors.New("invalid protocol version requested")
}
// Resolve the remote NTP server address.
raddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(host, "123"))
if err != nil {
return nil, 0, err
}
// Resolve the local address if specified as an option.
var laddr *net.UDPAddr
if opt.LocalAddress != "" {
laddr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(opt.LocalAddress, "0"))
if err != nil {
return nil, 0, err
}
}
// Override the port if requested.
if opt.Port != 0 {
raddr.Port = opt.Port
}
// Prepare a "connection" to the remote server.
con, err := net.DialUDP("udp", laddr, raddr)
if err != nil {
return nil, 0, err
}
defer con.Close()
// Set a TTL for the packet if requested.
if opt.TTL != 0 {
ipcon := ipv4.NewConn(con)
err = ipcon.SetTTL(opt.TTL)
if err != nil {
return nil, 0, err
}
}
// Set a timeout on the connection.
if opt.Timeout == 0 {
opt.Timeout = defaultTimeout
}
con.SetDeadline(time.Now().Add(opt.Timeout))
// Allocate a message to hold the response.
recvMsg := new(msg)
// Allocate a message to hold the query.
xmitMsg := new(msg)
xmitMsg.setMode(client)
xmitMsg.setVersion(opt.Version)
xmitMsg.setLeap(LeapNotInSync)
// To ensure privacy and prevent spoofing, try to use a random 64-bit
// value for the TransmitTime. If crypto/rand couldn't generate a
// random value, fall back to using the system clock. Keep track of
// when the messsage was actually transmitted.
bits := make([]byte, 8)
_, err = rand.Read(bits)
var xmitTime time.Time
if err == nil {
xmitMsg.TransmitTime = ntpTime(binary.BigEndian.Uint64(bits))
xmitTime = time.Now()
} else {
xmitTime = time.Now()
xmitMsg.TransmitTime = toNtpTime(xmitTime)
}
// Transmit the query.
err = binary.Write(con, binary.BigEndian, xmitMsg)
if err != nil {
return nil, 0, err
}
// Receive the response.
err = binary.Read(con, binary.BigEndian, recvMsg)
if err != nil {
return nil, 0, err
}
// Keep track of the time the response was received.
delta := time.Since(xmitTime)
if delta < 0 {
// The local system may have had its clock adjusted since it
// sent the query. In go 1.9 and later, time.Since ensures
// that a monotonic clock is used, so delta can never be less
// than zero. In versions before 1.9, a monotonic clock is
// not used, so we have to check.
return nil, 0, errors.New("client clock ticked backwards")
}
recvTime := toNtpTime(xmitTime.Add(delta))
// Check for invalid fields.
if recvMsg.getMode() != server {
return nil, 0, errors.New("invalid mode in response")
}
if recvMsg.TransmitTime == ntpTime(0) {
return nil, 0, errors.New("invalid transmit time in response")
}
if recvMsg.OriginTime != xmitMsg.TransmitTime {
return nil, 0, errors.New("server response mismatch")
}
if recvMsg.ReceiveTime > recvMsg.TransmitTime {
return nil, 0, errors.New("server clock ticked backwards")
}
// Correct the received message's origin time using the actual
// transmit time.
recvMsg.OriginTime = toNtpTime(xmitTime)
return recvMsg, recvTime, nil
}
// parseTime parses the NTP packet along with the packet receive time to
// generate a Response record.
func parseTime(m *msg, recvTime ntpTime) *Response {
r := &Response{
Time: m.TransmitTime.Time(),
ClockOffset: offset(m.OriginTime, m.ReceiveTime, m.TransmitTime, recvTime),
RTT: rtt(m.OriginTime, m.ReceiveTime, m.TransmitTime, recvTime),
Precision: toInterval(m.Precision),
Stratum: m.Stratum,
ReferenceID: m.ReferenceID,
ReferenceTime: m.ReferenceTime.Time(),
RootDelay: m.RootDelay.Duration(),
RootDispersion: m.RootDispersion.Duration(),
Leap: m.getLeap(),
MinError: minError(m.OriginTime, m.ReceiveTime, m.TransmitTime, recvTime),
Poll: toInterval(m.Poll),
}
// Calculate values depending on other calculated values
r.RootDistance = rootDistance(r.RTT, r.RootDelay, r.RootDispersion)
// If a kiss of death was received, interpret the reference ID as
// a kiss code.
if r.Stratum == 0 {
r.KissCode = kissCode(r.ReferenceID)
}
return r
}
// The following helper functions calculate additional metadata about the
// timestamps received from an NTP server. The timestamps returned by
// the server are given the following variable names:
//
// org = Origin Timestamp (client send time)
// rec = Receive Timestamp (server receive time)
// xmt = Transmit Timestamp (server reply time)
// dst = Destination Timestamp (client receive time)
func rtt(org, rec, xmt, dst ntpTime) time.Duration {
// round trip delay time
// rtt = (dst-org) - (xmt-rec)
a := dst.Time().Sub(org.Time())
b := xmt.Time().Sub(rec.Time())
rtt := a - b
if rtt < 0 {
rtt = 0
}
return rtt
}
func offset(org, rec, xmt, dst ntpTime) time.Duration {
// local clock offset
// offset = ((rec-org) + (xmt-dst)) / 2
a := rec.Time().Sub(org.Time())
b := xmt.Time().Sub(dst.Time())
return (a + b) / time.Duration(2)
}
func minError(org, rec, xmt, dst ntpTime) time.Duration {
// Each NTP response contains two pairs of send/receive timestamps.
// When either pair indicates a "causality violation", we calculate the
// error as the difference in time between them. The minimum error is
// the greater of the two causality violations.
var error0, error1 ntpTime
if org >= rec {
error0 = org - rec
}
if xmt >= dst {
error1 = xmt - dst
}
if error0 > error1 {
return error0.Duration()
}
return error1.Duration()
}
func rootDistance(rtt, rootDelay, rootDisp time.Duration) time.Duration {
// The root distance is:
// the maximum error due to all causes of the local clock
// relative to the primary server. It is defined as half the
// total delay plus total dispersion plus peer jitter.
// (https://tools.ietf.org/html/rfc5905#appendix-A.5.5.2)
//
// In the reference implementation, it is calculated as follows:
// rootDist = max(MINDISP, rootDelay + rtt)/2 + rootDisp
// + peerDisp + PHI * (uptime - peerUptime)
// + peerJitter
// For an SNTP client which sends only a single packet, most of these
// terms are irrelevant and become 0.
totalDelay := rtt + rootDelay
return totalDelay/2 + rootDisp
}
func toInterval(t int8) time.Duration {
switch {
case t > 0:
return time.Duration(uint64(time.Second) << uint(t))
case t < 0:
return time.Duration(uint64(time.Second) >> uint(-t))
default:
return time.Second
}
}
func kissCode(id uint32) string {
isPrintable := func(ch byte) bool { return ch >= 32 && ch <= 126 }
b := []byte{
byte(id >> 24),
byte(id >> 16),
byte(id >> 8),
byte(id),
}
for _, ch := range b {
if !isPrintable(ch) {
return ""
}
}
return string(b)
}