summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2018-12-18 10:06:07 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2018-12-18 10:06:07 +0100
commit5a0633d70a82e15f63a006489ffa1544fa37cb90 (patch)
tree5bc9ff8c7721a7f15b5fa322d50ebeed51225e9a
parentc56781de33a257cc83978132dee0b28e2cbfc719 (diff)
downloaddabmux-5a0633d70a82e15f63a006489ffa1544fa37cb90.tar.gz
dabmux-5a0633d70a82e15f63a006489ffa1544fa37cb90.tar.bz2
dabmux-5a0633d70a82e15f63a006489ffa1544fa37cb90.zip
Allow user to specify TAI bulletin URLs
-rw-r--r--doc/example.mux7
-rw-r--r--src/ClockTAI.cpp59
-rw-r--r--src/ClockTAI.h6
-rw-r--r--src/DabMultiplexer.cpp15
4 files changed, 72 insertions, 15 deletions
diff --git a/doc/example.mux b/doc/example.mux
index 1ecffaf..48a89dc 100644
--- a/doc/example.mux
+++ b/doc/example.mux
@@ -50,6 +50,13 @@ general {
; your file is still valid.
tist false
+ ; The URLs used to fetch the TAI bulletin can be overridden if needed.
+ ; URLs are given as a pipe-separated list, and the default value is:
+ ;tai_clock_bulletins "https://www.ietf.org/timezones/data/leap-seconds.list|https://raw.githubusercontent.com/eggert/tz/master/leap-seconds.list"
+ ;
+ ; You may also use a file:// URL if you take care of updating the file
+ ; yourself and store it locally.
+
; The management server is a simple TCP server that can present
; statistics data (buffers, overruns, underruns, etc)
; which can then be graphed a tool like Munin
diff --git a/src/ClockTAI.cpp b/src/ClockTAI.cpp
index 875fce2..7fef72b 100644
--- a/src/ClockTAI.cpp
+++ b/src/ClockTAI.cpp
@@ -69,8 +69,8 @@ const int64_t ntp_unix_offset = 2208988800L;
// leap seconds insertion bulletin is available from the IETF and in the TZ
// distribution
-static array<const char*, 2> tai_urls = {
- "http://www.ietf.org/timezones/data/leap-seconds.list",
+static array<const char*, 2> default_tai_urls = {
+ "https://www.ietf.org/timezones/data/leap-seconds.list",
"https://raw.githubusercontent.com/eggert/tz/master/leap-seconds.list",
};
@@ -86,10 +86,25 @@ static array<const char*, 2> tai_cache_locations = {
"/tmp/odr-dabmux-leap-seconds.cache",
};
-ClockTAI::ClockTAI() :
+ClockTAI::ClockTAI(const std::vector<std::string>& bulletin_urls) :
RemoteControllable("clocktai")
{
RC_ADD_PARAMETER(expiry, "Number of seconds until TAI Bulletin expires");
+
+ if (bulletin_urls.empty()) {
+ etiLog.level(debug) << "Initialising default TAI Bulletin URLs";
+ for (const auto url : default_tai_urls) {
+ m_bulletin_urls.push_back(url);
+ }
+ }
+ else {
+ etiLog.level(debug) << "Initialising user-configured TAI Bulletin URLs";
+ m_bulletin_urls = bulletin_urls;
+ }
+
+ for (const auto url : m_bulletin_urls) {
+ etiLog.level(info) << "TAI Bulletin URL: '" << url << "'";
+ }
}
int ClockTAI::get_valid_offset()
@@ -97,6 +112,8 @@ int ClockTAI::get_valid_offset()
int offset = 0;
bool offset_valid = false;
+ std::unique_lock<std::mutex> lock(m_data_mutex);
+
if (bulletin_is_valid()) {
#if TEST
etiLog.level(info) << "Bulletin already valid";
@@ -120,19 +137,22 @@ int ClockTAI::get_valid_offset()
offset_valid = true;
}
else {
- for (const auto url : tai_urls) {
+ for (const auto url : m_bulletin_urls) {
try {
- download_tai_utc_bulletin(url);
#if TEST
etiLog.level(info) << "Load bulletin from " << url;
#endif
+ download_tai_utc_bulletin(url.c_str());
if (bulletin_is_valid()) {
-#if TEST
- etiLog.level(info) << "Bulletin from " << url << " valid";
-#endif
offset = parse_ietf_bulletin();
+ etiLog.level(debug) << "Loaded valid TAI Bulletin from " <<
+ url << " giving offset=" << offset;
offset_valid = true;
}
+ else {
+ etiLog.level(debug) << "Skipping invalid TAI bulletin from "
+ << url;
+ }
}
catch (const runtime_error& e) {
etiLog.level(warn) <<
@@ -171,12 +191,14 @@ int ClockTAI::get_valid_offset()
int ClockTAI::get_offset()
{
using namespace std::chrono;
- auto time_now = system_clock::now();
+ const auto time_now = system_clock::now();
std::unique_lock<std::mutex> lock(m_data_mutex);
if (not m_offset_valid) {
#ifdef TEST
+ // Assume we've downloaded it in the past:
+
m_offset = 37; // Valid in early 2017
m_offset_valid = true;
@@ -185,7 +207,14 @@ int ClockTAI::get_offset()
#else
// First time we run we must block until we know
// the offset
- m_offset = get_valid_offset();
+ lock.unlock();
+ try {
+ m_offset = get_valid_offset();
+ }
+ catch (const download_failed&) {
+ throw runtime_error("Unable to download TAI bulletin");
+ }
+ lock.lock();
m_offset_valid = true;
m_bulletin_download_time = system_clock::now();
#endif
@@ -196,6 +225,7 @@ int ClockTAI::get_offset()
if (time_now - m_bulletin_download_time > hours(24 * 31)) {
// Refresh if it's older than one month. Leap seconds are
// announced several months in advance
+ etiLog.level(debug) << "Trying to refresh TAI bulletin";
if (m_offset_future.valid()) {
auto state = m_offset_future.wait_for(seconds(0));
@@ -211,8 +241,8 @@ int ClockTAI::get_offset()
}
catch (const download_failed&) {
etiLog.level(warn) <<
- "TAI-UTC download failed, will retry in " +
- to_string(download_retry_interval_hours) + " hour(s)";
+ "TAI-UTC download failed, will retry in " <<
+ download_retry_interval_hours << " hour(s)";
}
#ifdef TEST
wait_longer = false;
@@ -409,6 +439,9 @@ int64_t ClockTAI::bulletin_expiry_delay() const
std::atoll(expiry_data_str.c_str()) - ntp_unix_offset;
if (expiry_unix > now) {
+#ifdef TEST
+ etiLog.level(info) << "Bulletin expires in " << expiry_unix - now;
+#endif
return expiry_unix - now;
}
}
@@ -516,7 +549,7 @@ int main(int argc, char **argv)
{
using namespace std;
- ClockTAI tai;
+ ClockTAI tai({});
while (wait_longer) {
try {
diff --git a/src/ClockTAI.h b/src/ClockTAI.h
index e0dc439..4436ba9 100644
--- a/src/ClockTAI.h
+++ b/src/ClockTAI.h
@@ -40,6 +40,8 @@
#include <chrono>
#include <future>
#include <mutex>
+#include <string>
+#include <vector>
#include "RemoteControl.h"
// EDI needs to know UTC-TAI, but doesn't need the CLOCK_TAI to be set.
@@ -49,7 +51,7 @@
/* Loads, parses and represents TAI-UTC offset information from the IETF bulletin */
class ClockTAI : public RemoteControllable {
public:
- ClockTAI();
+ ClockTAI(const std::vector<std::string>& bulletin_urls);
// Fetch the bulletin from the IETF website and return the current
// TAI-UTC offset.
@@ -81,6 +83,8 @@ class ClockTAI : public RemoteControllable {
int m_offset = 0;
int m_offset_valid = false;
+ std::vector<std::string> m_bulletin_urls;
+
mutable std::stringstream m_bulletin;
std::chrono::system_clock::time_point m_bulletin_download_time;
diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp
index 84d9704..719e767 100644
--- a/src/DabMultiplexer.cpp
+++ b/src/DabMultiplexer.cpp
@@ -66,6 +66,19 @@ const unsigned short BitRateTable[64] = {
384, 384, 384
};
+static vector<string> split_pipe_separated_string(const std::string& s)
+{
+ stringstream ss;
+ ss << s;
+
+ string elem;
+ vector<string> components;
+ while (getline(ss, elem, '|')) {
+ components.push_back(elem);
+ }
+ return components;
+}
+
DabMultiplexer::DabMultiplexer(
boost::property_tree::ptree pt) :
RemoteControllable("mux"),
@@ -76,7 +89,7 @@ DabMultiplexer::DabMultiplexer(
currentFrame(0),
ensemble(std::make_shared<dabEnsemble>()),
m_tai_clock_required(false),
- m_clock_tai(),
+ m_clock_tai(split_pipe_separated_string(pt.get("general.tai_clock_bulletins", ""))),
fig_carousel(ensemble)
{
RC_ADD_PARAMETER(frames,