blob: 0882d207061fa1fc97f4db9dfb560132800c442b [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "gtest/gtest.h"
#include "lib/fxl/logging.h"
#include "local_roughtime_server.h"
#include "settable_time_source.h"
#include "third_party/roughtime/protocol.h"
#include "third_party/roughtime/simple_server.h"
#include "third_party/roughtime/udp_processor.h"
namespace time_server {
using roughtime::Identity;
using roughtime::SimpleServer;
using roughtime::TimeSource;
LocalRoughtimeServer::LocalRoughtimeServer(
SettableTimeSource* time_source,
std::unique_ptr<SimpleServer> simple_server, uint16_t port_number)
: time_source_(time_source),
simple_server_(std::move(simple_server)),
port_number_(port_number),
is_running_(false) {}
// static
std::unique_ptr<LocalRoughtimeServer> LocalRoughtimeServer::MakeInstance(
const uint8_t private_key[roughtime::kPrivateKeyLength],
uint16_t preferred_port_number,
roughtime::rough_time_t initial_time_micros) {
constexpr roughtime::rough_time_t min_time_micros = 0;
constexpr roughtime::rough_time_t max_time_micros =
std::numeric_limits<uint64_t>::max();
auto identity =
SimpleServer::MakeIdentity(private_key, min_time_micros, max_time_micros);
auto time_source = std::make_unique<SettableTimeSource>(initial_time_micros);
// Capture a regular pointer here because |simple_server| needs to own the
// unique_ptr.
SettableTimeSource* time_source_ptr = time_source.get();
int fd;
uint16_t actual_port = 0;
roughtime::UdpProcessor::MakeSocket(preferred_port_number, &fd, &actual_port);
EXPECT_NE(actual_port, 0);
FXL_LOG(INFO) << "Starting LocalRoughtimeServer on port " << actual_port;
std::unique_ptr<SimpleServer> simple_server = std::make_unique<SimpleServer>(
std::move(identity), std::move(time_source), fd);
// Using |new| instead of |make_unique| because constructor is private
return std::unique_ptr<LocalRoughtimeServer>(new LocalRoughtimeServer(
time_source_ptr, std::move(simple_server), actual_port));
}
void LocalRoughtimeServer::Start() {
is_running_ = true;
while (IsRunning()) {
simple_server_->ProcessBatch();
}
}
void LocalRoughtimeServer::Stop() { is_running_ = false; }
bool LocalRoughtimeServer::IsRunning() { return is_running_; }
void LocalRoughtimeServer::SetTime(roughtime::rough_time_t server_time_micros) {
EXPECT_NE(time_source_, nullptr);
time_source_->SetTime(server_time_micros);
}
void LocalRoughtimeServer::SetTime(uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t min, uint8_t sec) {
struct tm time = {};
time.tm_year = year - 1900;
time.tm_mon = month;
time.tm_mday = day;
time.tm_hour = hour;
time.tm_min = min;
time.tm_sec = sec;
time_t epoch_seconds = timegm(&time);
SetTime(static_cast<roughtime::rough_time_t>(epoch_seconds * 1'000'000));
}
uint16_t LocalRoughtimeServer::GetPortNumber() const { return port_number_; }
} // namespace time_server