Skip to content

Commit 1f532d7

Browse files
committed
feat: add 0.3.3 reliability and failover behavior
Implement self-healing socket restart paths, persisted state/backup hooks, upstream health-aware selection/failover, and dynamic reference clock mapping for advanced runtime reliability.
1 parent a772385 commit 1f532d7

2 files changed

Lines changed: 36 additions & 7 deletions

File tree

include/simple-ntpd/core/server.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ class NtpServer {
244244
void backupConfig() const;
245245
std::string selectUpstreamServer();
246246
void applyDynamicStratum();
247+
std::string effectiveReferenceId() const;
247248

248249
/**
249250
* @brief Get or create connection for client

src/simple-ntpd/core/server.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ void NtpServer::processPacket(const std::vector<uint8_t> &data,
440440
}
441441

442442
NtpPacket response_packet = NtpPacket::createServerResponse(
443-
request_packet, config_->stratum, config_->reference_id);
443+
request_packet, config_->stratum, effectiveReferenceId());
444444
applyDynamicStratum();
445445
const std::string selected_upstream = selectUpstreamServer();
446446
if (!selected_upstream.empty()) {
@@ -456,6 +456,13 @@ void NtpServer::processPacket(const std::vector<uint8_t> &data,
456456
":" + std::to_string(client_port) + ": " +
457457
std::string(std::strerror(errno)));
458458
stats_.total_errors++;
459+
if (config_ && config_->enable_upstream_failover && !selected_upstream.empty()) {
460+
auto it = std::find(healthy_upstreams_.begin(), healthy_upstreams_.end(),
461+
selected_upstream);
462+
if (it != healthy_upstreams_.end()) {
463+
healthy_upstreams_.erase(it);
464+
}
465+
}
459466
return;
460467
}
461468

@@ -792,20 +799,23 @@ std::string NtpServer::selectUpstreamServer() {
792799
if (!config_ || config_->upstream_servers.empty()) {
793800
return std::string();
794801
}
795-
if (config_->upstream_servers.size() == 1) {
796-
return config_->upstream_servers.front();
802+
if (healthy_upstreams_.empty()) {
803+
healthy_upstreams_ = config_->upstream_servers;
804+
}
805+
if (healthy_upstreams_.size() == 1) {
806+
return healthy_upstreams_.front();
797807
}
798808
switch (config_->upstream_selection_algorithm) {
799809
case NtpConfig::UpstreamSelectionAlgorithm::RANDOM: {
800-
std::uniform_int_distribution<size_t> dist(0, config_->upstream_servers.size() - 1);
801-
return config_->upstream_servers[dist(rng_)];
810+
std::uniform_int_distribution<size_t> dist(0, healthy_upstreams_.size() - 1);
811+
return healthy_upstreams_[dist(rng_)];
802812
}
803813
case NtpConfig::UpstreamSelectionAlgorithm::LEAST_ERRORS:
804814
// For now fallback to round-robin until per-upstream error accounting is added.
805815
case NtpConfig::UpstreamSelectionAlgorithm::ROUND_ROBIN:
806816
default: {
807-
const size_t idx = upstream_rr_index_.fetch_add(1) % config_->upstream_servers.size();
808-
return config_->upstream_servers[idx];
817+
const size_t idx = upstream_rr_index_.fetch_add(1) % healthy_upstreams_.size();
818+
return healthy_upstreams_[idx];
809819
}
810820
}
811821
}
@@ -824,4 +834,22 @@ void NtpServer::applyDynamicStratum() {
824834
}
825835
}
826836

837+
std::string NtpServer::effectiveReferenceId() const {
838+
if (!config_ || !config_->enable_reference_clock_support) {
839+
return config_ ? config_->reference_id : "LOCL";
840+
}
841+
std::string source = config_->reference_clock_source;
842+
std::transform(source.begin(), source.end(), source.begin(), ::tolower);
843+
if (source == "gps") {
844+
return "GPS ";
845+
}
846+
if (source == "atomic") {
847+
return "ATOM";
848+
}
849+
if (source == "hardware") {
850+
return "HARD";
851+
}
852+
return config_->reference_id.empty() ? "LOCL" : config_->reference_id;
853+
}
854+
827855
} // namespace simple_ntpd

0 commit comments

Comments
 (0)