1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved. 2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be 3*3f982cf4SFabien Sanglard // found in the LICENSE file. 4*3f982cf4SFabien Sanglard 5*3f982cf4SFabien Sanglard #include "cast/streaming/ntp_time.h" 6*3f982cf4SFabien Sanglard 7*3f982cf4SFabien Sanglard #include "util/osp_logging.h" 8*3f982cf4SFabien Sanglard 9*3f982cf4SFabien Sanglard namespace openscreen { 10*3f982cf4SFabien Sanglard namespace cast { 11*3f982cf4SFabien Sanglard 12*3f982cf4SFabien Sanglard namespace { 13*3f982cf4SFabien Sanglard 14*3f982cf4SFabien Sanglard // The number of seconds between 1 January 1900 and 1 January 1970. 15*3f982cf4SFabien Sanglard constexpr NtpSeconds kTimeBetweenNtpEpochAndUnixEpoch{INT64_C(2208988800)}; 16*3f982cf4SFabien Sanglard 17*3f982cf4SFabien Sanglard } // namespace 18*3f982cf4SFabien Sanglard NtpTimeConverter(Clock::time_point now,std::chrono::seconds since_unix_epoch)19*3f982cf4SFabien SanglardNtpTimeConverter::NtpTimeConverter(Clock::time_point now, 20*3f982cf4SFabien Sanglard std::chrono::seconds since_unix_epoch) 21*3f982cf4SFabien Sanglard : start_time_(now), 22*3f982cf4SFabien Sanglard since_ntp_epoch_( 23*3f982cf4SFabien Sanglard std::chrono::duration_cast<NtpSeconds>(since_unix_epoch) + 24*3f982cf4SFabien Sanglard kTimeBetweenNtpEpochAndUnixEpoch) {} 25*3f982cf4SFabien Sanglard 26*3f982cf4SFabien Sanglard NtpTimeConverter::~NtpTimeConverter() = default; 27*3f982cf4SFabien Sanglard ToNtpTimestamp(Clock::time_point time_point) const28*3f982cf4SFabien SanglardNtpTimestamp NtpTimeConverter::ToNtpTimestamp( 29*3f982cf4SFabien Sanglard Clock::time_point time_point) const { 30*3f982cf4SFabien Sanglard const Clock::duration time_since_start = time_point - start_time_; 31*3f982cf4SFabien Sanglard const auto whole_seconds = 32*3f982cf4SFabien Sanglard std::chrono::duration_cast<NtpSeconds>(time_since_start); 33*3f982cf4SFabien Sanglard const auto remainder = 34*3f982cf4SFabien Sanglard std::chrono::duration_cast<NtpFraction>(time_since_start - whole_seconds); 35*3f982cf4SFabien Sanglard return AssembleNtpTimestamp(since_ntp_epoch_ + whole_seconds, remainder); 36*3f982cf4SFabien Sanglard } 37*3f982cf4SFabien Sanglard ToLocalTime(NtpTimestamp timestamp) const38*3f982cf4SFabien SanglardClock::time_point NtpTimeConverter::ToLocalTime(NtpTimestamp timestamp) const { 39*3f982cf4SFabien Sanglard auto ntp_seconds = NtpSecondsPart(timestamp); 40*3f982cf4SFabien Sanglard // Year 2036 wrap-around check: If the NTP timestamp appears to be a 41*3f982cf4SFabien Sanglard // point-in-time before 1970, assume the 2036 wrap-around has occurred, and 42*3f982cf4SFabien Sanglard // adjust to compensate. 43*3f982cf4SFabien Sanglard if (ntp_seconds <= kTimeBetweenNtpEpochAndUnixEpoch) { 44*3f982cf4SFabien Sanglard constexpr NtpSeconds kNtpSecondsPerEra{INT64_C(1) << 32}; 45*3f982cf4SFabien Sanglard ntp_seconds += kNtpSecondsPerEra; 46*3f982cf4SFabien Sanglard } 47*3f982cf4SFabien Sanglard 48*3f982cf4SFabien Sanglard const auto whole_seconds = ntp_seconds - since_ntp_epoch_; 49*3f982cf4SFabien Sanglard const auto seconds_since_start = 50*3f982cf4SFabien Sanglard Clock::to_duration(whole_seconds) + start_time_; 51*3f982cf4SFabien Sanglard const auto remainder = Clock::to_duration(NtpFractionPart(timestamp)); 52*3f982cf4SFabien Sanglard return seconds_since_start + remainder; 53*3f982cf4SFabien Sanglard } 54*3f982cf4SFabien Sanglard 55*3f982cf4SFabien Sanglard } // namespace cast 56*3f982cf4SFabien Sanglard } // namespace openscreen 57