blob: e42026fd0c3190725577f50e1362ba58218d5235 [file] [log] [blame] [view]
# HTTPSDate Timesource
The HTTPSDate Timesource implements the
[`fuchsia.time.external.PushSource`][time-fidl] protocol. It retrieves time
samples by calling an HTTPS URL specified in the component configuration and
pulling the time off the Date header in the response. HTTPSDate relies on the
underlying TLS connection for server authentication. As the device on which
HTTPSDate is running may not have a valid UTC time, expiry dates on TLS
certificates are checked for consistency against the time reported by the
server.
## Key Assumptions
HTTPSDate relies on the server to conform to the standards defined for the Date
HTTP header as defined in [RFC 2616][rfc-2616], in particular that the server
has a reasonably accurate time, and that the date is sampled at the time of
message generation.
HTTPSDate also relies on some assumptions not in the RFC:
* The servers polled to produce a single sample are synced to the same time
source.
* The servers truncate time down to the second.
When these additional assumptions break down, the accuracy of time on the
device is affected:
* If servers are inconsistently synced or truncated the time samples produced
will likely contain more noise.
* If servers consistently round time in a different manner (such as rounding
up) the time samples will contain a systemic error of up to a second.
## Design Overview
HTTPSDate contains an algorithm to produce a sample from network polls, and a
scheduler that determines when to produce a sample.
### Sampling Algorithm
The sampling algorithm is responsible for producing a single time sample.
A fundamental limitation of using HTTP Date headers is that the header has a
resolution of seconds. The sampling algorithm attempts to improve the
resolution of a produced sample by combining the results of multiple polls.
Note that for simplicity the discussion here ignores the effects of network
latency and drift between the device and server's clock, but they are taken
into account in the implementation.
The algorithm encapsulates the information obtained from polling a server once
in a _bound_. A _bound_ is a tuple `(monotonic, utc_min, utc_max)` that defines
the range of possible UTC times for a given monotonic time. When a server is
polled at monotonic time `t_mono`, the server returns some UTC time `t_server`.
Because the server is assumed to truncate time down to the nearest second,
`t_server` is a whole number of seconds, and the actual UTC time at `t_mono` is
in the range `[t_server, t_server + 1]`. This is expressed as the bound
`(t_mono, t_server, t_server + 1)`.
The following operations are possible on bounds:
* _Projection_ - A bound `(t_mono, t_utc_min, t_utc_max)` may be _projected_ to
a later monotonic time `t_mono_later` by adding `t_mono_later - t_mono` to each
value in the tuple.
* _Combination_ - Two bounds at the same monotonic time may be _combined_ by
taking the intersection of their UTC ranges. _Combining_ two polls produces
a single bound that usually has a smaller bound and therefore lower
uncertainty.
These operations allow combining the results of any two polls by _projecting_
the earlier bound to the time of the later poll, then _combining_ the resulting
polls.
The algorithm polls the server a few times and combines the resulting bounds
into a single tighter bound. The algorithm makes a best effort to poll at
intervals such that the size of the accumulated bound is halved after each
poll. The final bound is then converted to a single sample.
### Scheduler
The scheduler is responsible for periodically producing samples by invoking the
sampling algorithm, and retrying in case of failure. The scheduler progresses
through three phases that invoke the sampling algorithm at different timings
and parameters:
* _Initial phase_ - comprised of the first sample only, which is produced with
fewer polls than subsequent polls. This optimizes to start the system clock as
early as possible at the cost of accuracy.
* _Converge phase_ - comprised of the first few subsequent samples. Samples are
produced relatively frequently so that the system clock can converge on an
accurate time.
* _Maintain phase_ - comprised of all remaining samples. Samples are produced
infrequently so that an accurate time can be maintained.
[time-fidl]: https://fuchsia.dev/reference/fidl/fuchsia.time.external#PushSource
[rfc-2616]: https://tools.ietf.org/html/rfc2616