query method

  1. @override
Future<NtpResponse> query({
  1. int samples = 1,
})
override

Queries the configured NTP server and returns a full NtpResponse with RFC 5905 telemetry.

When samples > 1, performs a multi-sample burst and selects the measurement with the lowest round-trip delay (RFC 5905 clock filter).

Implementation

@override
Future<NtpResponse> query({int samples = 1}) async {
  assert(samples >= 1, 'samples must be at least 1.');
  final ntpAddress = await _resolveAddress();

  _RawNtpSample? bestSample;
  Object? lastError;
  StackTrace? lastStack;

  for (var i = 0; i < samples; i++) {
    try {
      final sample = await _querySingleSample(ntpAddress);
      if (bestSample == null || sample.rttMicros < bestSample.rttMicros) {
        bestSample = sample;
      }
    } catch (e, s) {
      lastError = e;
      lastStack = s;
      if (samples == 1) rethrow;
    }
  }

  if (bestSample == null) {
    Error.throwWithStackTrace(
      lastError ?? Exception('All $samples NTP samples failed'),
      lastStack ?? StackTrace.current,
    );
  }

  // Apply offset after all async cleanup has finished to prevent microtask/socket lag.
  final correctedTime =
      DateTime.now().add(Duration(microseconds: bestSample.offsetMicros));
  return NtpResponse(
    dateTime: isUtc ? correctedTime.toUtc() : correctedTime.toLocal(),
    offset: Duration(microseconds: bestSample.offsetMicros),
    roundTripDelay: Duration(microseconds: bestSample.rttMicros),
    server: server,
    stratum: bestSample.stratum,
    leapIndicator: bestSample.leapIndicator,
    referenceId: bestSample.referenceId,
    rootDelay: Duration(microseconds: bestSample.rootDelayMicros),
    rootDispersion: Duration(microseconds: bestSample.rootDispersionMicros),
  );
}