aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2018-01-23 08:57:43 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2018-01-23 08:57:43 +0100
commitacfabd815f1be870ea01120248384c663832e2b2 (patch)
tree9fe568ce8807f16f94a41af986590013da2a971e
parente3bdb3bb6e089dadff0727e86fb7441bcc58c788 (diff)
downloaddabmux-acfabd815f1be870ea01120248384c663832e2b2.tar.gz
dabmux-acfabd815f1be870ea01120248384c663832e2b2.tar.bz2
dabmux-acfabd815f1be870ea01120248384c663832e2b2.zip
Handle download failure in TAI bulletin download and replace boost regex with std
-rw-r--r--m4/ax_boost_regex.m4111
-rw-r--r--src/ClockTAI.cpp112
-rw-r--r--src/ClockTAI.h7
-rw-r--r--src/Makefile.am2
-rw-r--r--src/dabOutput/dabOutputUdp.cpp9
5 files changed, 72 insertions, 169 deletions
diff --git a/m4/ax_boost_regex.m4 b/m4/ax_boost_regex.m4
deleted file mode 100644
index e2413c2..0000000
--- a/m4/ax_boost_regex.m4
+++ /dev/null
@@ -1,111 +0,0 @@
-# ===========================================================================
-# https://www.gnu.org/software/autoconf-archive/ax_boost_regex.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_BOOST_REGEX
-#
-# DESCRIPTION
-#
-# Test for Regex library from the Boost C++ libraries. The macro requires
-# a preceding call to AX_BOOST_BASE. Further documentation is available at
-# <http://randspringer.de/boost/index.html>.
-#
-# This macro calls:
-#
-# AC_SUBST(BOOST_REGEX_LIB)
-#
-# And sets:
-#
-# HAVE_BOOST_REGEX
-#
-# LICENSE
-#
-# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
-# Copyright (c) 2008 Michael Tindal
-#
-# Copying and distribution of this file, with or without modification, are
-# permitted in any medium without royalty provided the copyright notice
-# and this notice are preserved. This file is offered as-is, without any
-# warranty.
-
-#serial 23
-
-AC_DEFUN([AX_BOOST_REGEX],
-[
- AC_ARG_WITH([boost-regex],
- AS_HELP_STRING([--with-boost-regex@<:@=special-lib@:>@],
- [use the Regex library from boost - it is possible to specify a certain library for the linker
- e.g. --with-boost-regex=boost_regex-gcc-mt-d-1_33_1 ]),
- [
- if test "$withval" = "no"; then
- want_boost="no"
- elif test "$withval" = "yes"; then
- want_boost="yes"
- ax_boost_user_regex_lib=""
- else
- want_boost="yes"
- ax_boost_user_regex_lib="$withval"
- fi
- ],
- [want_boost="yes"]
- )
-
- if test "x$want_boost" = "xyes"; then
- AC_REQUIRE([AC_PROG_CC])
- CPPFLAGS_SAVED="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
- export CPPFLAGS
-
- LDFLAGS_SAVED="$LDFLAGS"
- LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
- export LDFLAGS
-
- AC_CACHE_CHECK(whether the Boost::Regex library is available,
- ax_cv_boost_regex,
- [AC_LANG_PUSH([C++])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/regex.hpp>
- ]],
- [[boost::regex r(); return 0;]])],
- ax_cv_boost_regex=yes, ax_cv_boost_regex=no)
- AC_LANG_POP([C++])
- ])
- if test "x$ax_cv_boost_regex" = "xyes"; then
- AC_DEFINE(HAVE_BOOST_REGEX,,[define if the Boost::Regex library is available])
- BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
- if test "x$ax_boost_user_regex_lib" = "x"; then
- for libextension in `ls $BOOSTLIBDIR/libboost_regex*.so* $BOOSTLIBDIR/libboost_regex*.dylib* $BOOSTLIBDIR/libboost_regex*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_regex.*\)\.so.*$;\1;' -e 's;^lib\(boost_regex.*\)\.dylib.*;\1;' -e 's;^lib\(boost_regex.*\)\.a.*$;\1;'` ; do
- ax_lib=${libextension}
- AC_CHECK_LIB($ax_lib, exit,
- [BOOST_REGEX_LIB="-l$ax_lib"; AC_SUBST(BOOST_REGEX_LIB) link_regex="yes"; break],
- [link_regex="no"])
- done
- if test "x$link_regex" != "xyes"; then
- for libextension in `ls $BOOSTLIBDIR/boost_regex*.dll* $BOOSTLIBDIR/boost_regex*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_regex.*\)\.dll.*$;\1;' -e 's;^\(boost_regex.*\)\.a.*$;\1;'` ; do
- ax_lib=${libextension}
- AC_CHECK_LIB($ax_lib, exit,
- [BOOST_REGEX_LIB="-l$ax_lib"; AC_SUBST(BOOST_REGEX_LIB) link_regex="yes"; break],
- [link_regex="no"])
- done
- fi
-
- else
- for ax_lib in $ax_boost_user_regex_lib boost_regex-$ax_boost_user_regex_lib; do
- AC_CHECK_LIB($ax_lib, main,
- [BOOST_REGEX_LIB="-l$ax_lib"; AC_SUBST(BOOST_REGEX_LIB) link_regex="yes"; break],
- [link_regex="no"])
- done
- fi
- if test "x$ax_lib" = "x"; then
- AC_MSG_ERROR(Could not find a version of the Boost::Regex library!)
- fi
- if test "x$link_regex" != "xyes"; then
- AC_MSG_ERROR(Could not link against $ax_lib !)
- fi
- fi
-
- CPPFLAGS="$CPPFLAGS_SAVED"
- LDFLAGS="$LDFLAGS_SAVED"
- fi
-])
diff --git a/src/ClockTAI.cpp b/src/ClockTAI.cpp
index b2a3e87..8c01127 100644
--- a/src/ClockTAI.cpp
+++ b/src/ClockTAI.cpp
@@ -3,7 +3,7 @@
2011, 2012 Her Majesty the Queen in Right of Canada (Communications
Research Center Canada)
- Copyright (C) 2017
+ Copyright (C) 2018
Matthias P. Braendli, matthias.braendli@mpb.li
http://www.opendigitalradio.org
@@ -29,7 +29,7 @@
* so that correct time can be communicated in EDI timestamps.
*
* This file contains self-test code that can be executed by running
- * g++ -g -Wall -DTEST -DHAVE_CURL -std=c++11 -lcurl -lboost_regex -pthread \
+ * g++ -g -Wall -DTEST -DHAVE_CURL -std=c++11 -lcurl -pthread \
* ClockTAI.cpp Log.cpp -o taitest && ./taitest
*/
@@ -53,12 +53,16 @@
#include <string>
#include <iostream>
#include <algorithm>
-#include <boost/regex.hpp>
+#include <regex>
+
+using namespace std;
#ifdef TEST
static bool wait_longer = true;
#endif
+constexpr int download_retry_interval_hours = 1;
+
// Offset between NTP time and POSIX time:
// timestamp_unix = timestamp_ntp - ntp_unix_offset
const int64_t ntp_unix_offset = 2208988800L;
@@ -109,7 +113,7 @@ int ClockTAI::get_valid_offset()
offset_valid = true;
}
}
- catch (std::runtime_error& e) {
+ catch (const runtime_error& e) {
etiLog.level(warn) <<
"TAI-UTC offset could not be retrieved from " <<
url << " : " << e.what();
@@ -127,25 +131,26 @@ int ClockTAI::get_valid_offset()
// With the current evolution of the offset, we're probably going
// to reach 500 long after DAB gets replaced by another standard.
if (offset < 0 or offset > 500) {
- std::stringstream ss;
+ stringstream ss;
ss << "TAI offset " << offset << " out of range";
- throw std::range_error(ss.str());
+ throw range_error(ss.str());
}
return offset;
}
else {
- // Try again in 1 hour
- m_bulletin_download_time += std::chrono::hours(1);
+ // Try again later
+ m_bulletin_download_time += chrono::hours(download_retry_interval_hours);
- throw std::runtime_error("Could not fetch TAI-UTC offset");
+ throw download_failed();
}
}
int ClockTAI::get_offset()
{
- auto time_now = std::chrono::system_clock::now();
+ using namespace std::chrono;
+ auto time_now = system_clock::now();
if (not m_offset_valid) {
#ifdef TEST
@@ -153,41 +158,46 @@ int ClockTAI::get_offset()
m_offset_valid = true;
// Simulate requiring a new download
- m_bulletin_download_time = std::chrono::system_clock::now() -
- std::chrono::hours(24 * 40);
+ m_bulletin_download_time = system_clock::now() - hours(24 * 40);
#else
// First time we run we must block until we know
// the offset
m_offset = get_valid_offset();
m_offset_valid = true;
- m_bulletin_download_time = std::chrono::system_clock::now();
+ m_bulletin_download_time = system_clock::now();
#endif
etiLog.level(info) <<
"Initialised TAI-UTC offset to " << m_offset << "s.";
}
- if (time_now - m_bulletin_download_time >
- std::chrono::seconds(3600 * 24 * 31)) {
+ 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
if (m_offset_future.valid()) {
- auto state = m_offset_future.wait_for(std::chrono::seconds(0));
+ auto state = m_offset_future.wait_for(seconds(0));
switch (state) {
- case std::future_status::ready:
- m_offset = m_offset_future.get();
- m_offset_valid = true;
- m_bulletin_download_time = std::chrono::system_clock::now();
-
- etiLog.level(info) <<
- "Updated TAI-UTC offset to " << m_offset << "s.";
+ case future_status::ready:
+ try {
+ m_offset = m_offset_future.get();
+ m_offset_valid = true;
+ m_bulletin_download_time = system_clock::now();
+
+ etiLog.level(info) <<
+ "Updated TAI-UTC offset to " << m_offset << "s.";
+ }
+ catch (const download_failed&) {
+ etiLog.level(warn) <<
+ "TAI-UTC download failed, will retry in " +
+ to_string(download_retry_interval_hours) + " hour(s)";
+ }
#ifdef TEST
wait_longer = false;
#endif
break;
- case std::future_status::deferred:
- case std::future_status::timeout:
+ case future_status::deferred:
+ case future_status::timeout:
// Not ready yet
#ifdef TEST
etiLog.level(debug) << " async not ready yet";
@@ -199,7 +209,7 @@ int ClockTAI::get_offset()
#ifdef TEST
etiLog.level(debug) << " Launch async";
#endif
- m_offset_future = std::async(std::launch::async,
+ m_offset_future = async(launch::async,
&ClockTAI::get_valid_offset, this);
}
}
@@ -230,12 +240,12 @@ int ClockTAI::parse_ietf_bulletin()
// Example Line:
// 3692217600 37 # 1 Jan 2017
//
- // NTP timestamp <TAB> leap seconds <TAB> # some comment
+ // NTP timestamp<TAB>leap seconds<TAB># some comment
// The NTP timestamp starts at epoch 1.1.1900.
// The difference between NTP timestamps and unix epoch is 70
// years i.e. 2208988800 seconds
- boost::regex regex_bulletin(R"(([0-9]+)\s+([0-9]+)\s+#.*)");
+ std::regex regex_bulletin(R"(([0-9]+)\s+([0-9]+)\s+#.*)");
time_t now = time(nullptr);
@@ -252,18 +262,18 @@ int ClockTAI::parse_ietf_bulletin()
* So we need to look at the current date, and compare it
* with the date of the leap second.
*/
- for (std::string line; std::getline(m_bulletin, line); ) {
+ for (string line; getline(m_bulletin, line); ) {
- boost::smatch bulletin_entry;
+ std::smatch bulletin_entry;
- bool is_match = boost::regex_search(line, bulletin_entry, regex_bulletin);
+ bool is_match = std::regex_search(line, bulletin_entry, regex_bulletin);
if (is_match) {
if (bulletin_entry.size() != 3) {
- throw std::runtime_error(
+ throw runtime_error(
"Incorrect number of matched TAI IETF bulletin entries");
}
- const std::string bulletin_ntp_timestamp(bulletin_entry[1]);
- const std::string bulletin_offset(bulletin_entry[2]);
+ const string bulletin_ntp_timestamp(bulletin_entry[1]);
+ const string bulletin_offset(bulletin_entry[2]);
const int64_t timestamp_unix =
std::atol(bulletin_ntp_timestamp.c_str()) - ntp_unix_offset;
@@ -276,16 +286,16 @@ int ClockTAI::parse_ietf_bulletin()
}
#if TEST
else {
- std::cerr << "IETF Ignoring offset " << bulletin_offset <<
+ cerr << "IETF Ignoring offset " << bulletin_offset <<
" at TS " << bulletin_ntp_timestamp <<
- " in the future" << std::endl;
+ " in the future" << endl;
}
#endif
}
}
if (not tai_utc_offset_valid) {
- throw std::runtime_error("No data in TAI bulletin");
+ throw runtime_error("No data in TAI bulletin");
}
return tai_utc_offset;
@@ -312,7 +322,7 @@ void ClockTAI::load_bulletin_from_file(const char* cache_filename)
m_bulletin.str("");
m_bulletin.clear();
- std::ifstream f(cache_filename);
+ ifstream f(cache_filename);
if (not f.good()) {
return;
}
@@ -323,9 +333,9 @@ void ClockTAI::load_bulletin_from_file(const char* cache_filename)
void ClockTAI::update_cache(const char* cache_filename)
{
- std::ofstream f(cache_filename);
+ ofstream f(cache_filename);
if (not f.good()) {
- throw std::runtime_error("TAI-UTC bulletin open cache for writing");
+ throw runtime_error("TAI-UTC bulletin open cache for writing");
}
m_bulletin.clear();
@@ -350,23 +360,23 @@ bool ClockTAI::bulletin_is_valid()
// The entry looks like this:
//#@ 3707596800
- boost::regex regex_expiration(R"(#@\s+([0-9]+))");
+ std::regex regex_expiration(R"(#@\s+([0-9]+))");
time_t now = time(nullptr);
m_bulletin.clear();
m_bulletin.seekg(0);
- for (std::string line; std::getline(m_bulletin, line); ) {
- boost::smatch bulletin_entry;
+ for (string line; getline(m_bulletin, line); ) {
+ std::smatch bulletin_entry;
- bool is_match = boost::regex_search(line, bulletin_entry, regex_expiration);
+ bool is_match = std::regex_search(line, bulletin_entry, regex_expiration);
if (is_match) {
if (bulletin_entry.size() != 2) {
- throw std::runtime_error(
+ throw runtime_error(
"Incorrect number of matched TAI IETF bulletin expiration");
}
- const std::string expiry_data_str(bulletin_entry[1]);
+ const string expiry_data_str(bulletin_entry[1]);
const int64_t expiry_unix =
std::atol(expiry_data_str.c_str()) - ntp_unix_offset;
@@ -399,12 +409,12 @@ void ClockTAI::download_tai_utc_bulletin(const char* url)
curl_easy_cleanup(curl);
if (res != CURLE_OK) {
- throw std::runtime_error( "TAI-UTC bulletin download failed: " +
- std::string(curl_easy_strerror(res)));
+ throw runtime_error( "TAI-UTC bulletin download failed: " +
+ string(curl_easy_strerror(res)));
}
}
#else
- throw std::runtime_error("Cannot download TAI Clock information without cURL");
+ throw runtime_error("Cannot download TAI Clock information without cURL");
#endif // HAVE_CURL
}
@@ -453,12 +463,12 @@ int main(int argc, char **argv)
etiLog.level(info) <<
"Offset is " << tai.get_offset();
}
- catch (std::exception &e) {
+ catch (const exception &e) {
etiLog.level(error) <<
"Exception " << e.what();
}
- std::this_thread::sleep_for(std::chrono::seconds(2));
+ this_thread::sleep_for(chrono::seconds(2));
}
return 0;
diff --git a/src/ClockTAI.h b/src/ClockTAI.h
index 99827ba..4ee4072 100644
--- a/src/ClockTAI.h
+++ b/src/ClockTAI.h
@@ -3,7 +3,7 @@
2011, 2012 Her Majesty the Queen in Right of Canada (Communications
Research Center Canada)
- Copyright (C) 2017
+ Copyright (C) 2018
Matthias P. Braendli, matthias.braendli@mpb.li
http://www.opendigitalradio.org
@@ -59,9 +59,12 @@ class ClockTAI {
#endif
private:
+ class download_failed {};
+
// Either retrieve the bulletin from the cache or if necessarly
// download it, and calculate the TAI-UTC offset.
- // Returns the offset.
+ // Returns the offset or throws download_failed or a range_error
+ // if the offset is out of bounds.
int get_valid_offset(void);
// Download of new bulletin is done asynchronously
diff --git a/src/Makefile.am b/src/Makefile.am
index cc9b032..1087588 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,7 +42,7 @@ endif
odr_dabmux_CFLAGS =-Wall -I$(FARSYNC_DIR) $(GITVERSION_FLAGS)
odr_dabmux_CXXFLAGS =-Wall -std=c++11 -I$(FARSYNC_DIR) $(GITVERSION_FLAGS) $(BOOST_CPPFLAGS) $(ZMQ_CPPFLAGS)
odr_dabmux_LDADD =$(ZMQ_LIBS) $(CURL_LIBS) $(BOOST_LDFLAGS) \
- -lpthread $(BOOST_SYSTEM_LIB) $(BOOST_THREAD_LIB) $(BOOST_REGEX_LIB) $(BOOST_ASIO_LIB)
+ -lpthread $(BOOST_SYSTEM_LIB) $(BOOST_THREAD_LIB) $(BOOST_ASIO_LIB)
odr_dabmux_SOURCES =DabMux.cpp DabMux.h \
DabMultiplexer.cpp DabMultiplexer.h \
diff --git a/src/dabOutput/dabOutputUdp.cpp b/src/dabOutput/dabOutputUdp.cpp
index 20e0c40..c129569 100644
--- a/src/dabOutput/dabOutputUdp.cpp
+++ b/src/dabOutput/dabOutputUdp.cpp
@@ -33,7 +33,7 @@
#include <cstring>
#include <cstdlib>
-#include <boost/regex.hpp>
+#include <regex>
#include <string>
#include <cstdio>
#include <limits.h>
@@ -54,14 +54,14 @@
int DabOutputUdp::Open(const char* name)
{
using namespace std;
- using namespace boost;
const string uri_without_proto(name);
regex re_url("([^:]+):([0-9]+)(.*)");
regex re_query("[?](?:src=([^&,]+))(?:[&,]ttl=([0-9]+))?");
smatch what;
- if (regex_match(uri_without_proto, what, re_url, match_default)) {
+ if (regex_match(uri_without_proto, what, re_url,
+ regex_constants::match_default)) {
string address = what[1];
if (this->packet_->getAddress().setAddress(address.c_str()) == -1) {
@@ -83,7 +83,8 @@ int DabOutputUdp::Open(const char* name)
string query_params = what[3];
smatch query_what;
- if (regex_match(query_params, query_what, re_query, match_default)) {
+ if (regex_match(query_params, query_what, re_query,
+ regex_constants::match_default)) {
string src = query_what[1];
int err = socket_->setMulticastSource(src.c_str());