Merge branch 'sm0svx:master' into svxreflector-authkey

This commit is contained in:
Adi Bier 2022-04-24 16:00:58 +02:00 committed by GitHub
commit 4473d1aa2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 147 additions and 124 deletions

View File

@ -117,7 +117,6 @@ using namespace Async;
****************************************************************************/
AtTimer::AtTimer(void)
: m_expire_offset(0)
{
timerclear(&m_expire_at);
m_timer.expired.connect(mem_fun(*this, &AtTimer::onTimerExpired));
@ -125,7 +124,6 @@ AtTimer::AtTimer(void)
AtTimer::AtTimer(struct tm &tm, bool do_start)
: m_expire_offset(0)
{
timerclear(&m_expire_at);
m_timer.expired.connect(mem_fun(*this, &AtTimer::onTimerExpired));

View File

@ -137,6 +137,8 @@ class AtTimer : public sigc::trackable
public:
/**
* @brief Default constructor
*
* After default construction the timer will be disabled.
*/
AtTimer(void);
@ -146,7 +148,7 @@ class AtTimer : public sigc::trackable
* @param do_start Set to \em true (default) if the timer should start
* upon creation
*/
AtTimer(struct tm &tm, bool do_start=true);
explicit AtTimer(struct tm &tm, bool do_start=true);
/**
* @brief Destructor
@ -202,9 +204,9 @@ class AtTimer : public sigc::trackable
protected:
private:
Timer m_timer;
Timer m_timer {-1};
struct timeval m_expire_at;
int m_expire_offset;
int m_expire_offset {0};
AtTimer(const AtTimer&);
AtTimer& operator=(const AtTimer&);

View File

@ -49,6 +49,7 @@ An example of how to use the StateMachine class
****************************************************************************/
#include <AsyncTimer.h>
#include <AsyncAtTimer.h>
/****************************************************************************
@ -173,6 +174,13 @@ class StateMachine
static_cast<StateTopBaseT*>(m_state)->timeoutEvent();
clearTimeout();
});
m_at_timer.expired.connect(
[&](AtTimer*)
{
assert(m_state != nullptr);
static_cast<StateTopBaseT*>(m_state)->timeoutAtEvent();
clearTimeoutAt();
});
}
/**
@ -287,8 +295,7 @@ class StateMachine
*
* Use this function to set a timeout to occur after the specified number
* of milliseconds. The timeoutEvent will be issued after the time has
* expired. The timeout will be automatically cleared when an exit from a
* state occur.
* expired.
*/
void setTimeout(int timeout_ms)
{
@ -296,6 +303,22 @@ class StateMachine
m_timer.setEnable(true);
}
/**
* @brief Set a timeout after which the timeoutAtEvent is issued
* @param tm The absolute time when the timeout should occur
* @param expire_offset A millisecond offset for the timer expiration
*
* Use this function to set a timeout to occur at the specified absolute
* time, plus or minus the offset value. The time is specified in local
* time. The timeoutAtEvent will be issued after the time has expired.
*/
void setTimeoutAt(struct tm& tm, int expire_offset=0)
{
m_at_timer.setTimeout(tm);
m_at_timer.setExpireOffset(expire_offset);
m_at_timer.start();
}
/**
* @brief Clear a pending timeout
*
@ -307,10 +330,22 @@ class StateMachine
m_timer.setEnable(false);
}
/**
* @brief Clear a pending absolute time timeout
*
* Use this function to immediately cancel a running absolute time timeout
* timer. See \ref setTimeoutAt for more information.
*/
void clearTimeoutAt(void)
{
m_at_timer.stop();
}
private:
StateTopT* m_state = nullptr;
ContextT* m_ctx = nullptr;
Timer m_timer = -1;
StateTopT* m_state = nullptr;
ContextT* m_ctx = nullptr;
Timer m_timer = -1;
AtTimer m_at_timer;
}; /* StateMachine */
@ -380,7 +415,6 @@ class StateBase : public ParentT
{
if (dynamic_cast<T*>(to) == nullptr)
{
ParentT::clearTimeout();
dynamic_cast<T*>(this)->exit();
ParentT::exitHandler(to);
}
@ -440,6 +474,11 @@ class StateBase : public ParentT
assert(!"Async::StateBase: Unhandled timeoutEvent");
}
virtual void timeoutAtEvent(void) override
{
assert(!"Async::StateBase: Unhandled timeoutAtEvent");
}
}; /* StateBase */
@ -508,11 +547,24 @@ class StateTopBase
*
* Use this function to set a timeout to occur after the specified number
* of milliseconds. The timeoutEvent will be issued after the time has
* expired. The timeout will be automatically cleared when an exit from a
* state occur.
* expired.
*/
void setTimeout(int timeout_ms) { m_sm->setTimeout(timeout_ms); }
/**
* @brief Set a timeout after which the timeoutAtEvent is issued
* @param tm The absolute time when the timeout should occur
* @param expire_offset A millisecond offset for the timer expiration
*
* Use this function to set a timeout to occur at the specified absolute
* time, plus or minus the offset value. The time is specified in local
* time. The timeoutAtEvent will be issued after the time has expired.
*/
void setTimeoutAt(struct tm& tm, int expire_offset=0)
{
m_sm->setTimeoutAt(tm, expire_offset);
}
/**
* @brief Clear a pending timeout
*
@ -521,6 +573,14 @@ class StateTopBase
*/
void clearTimeout(void) { m_sm->clearTimeout(); }
/**
* @brief Clear a pending absolute time timeout
*
* Use this function to immediately cancel a running absolute time timeout
* timer. See \ref setTimeoutAt for more information.
*/
void clearTimeoutAt(void) { m_sm->clearTimeoutAt(); }
/**
* @brief Get the typeid for this state
*/
@ -556,6 +616,19 @@ class StateTopBase
*/
virtual void timeoutEvent(void) = 0;
/**
* @brief Event function called when an absolute time timeout occurs
*
* This event function will be called when an absolute time timeout,
* previously set up using the setTimeoutAt function, has occurred.
*
* As all event functions this is a virtual function which work like any
* other virtual function in C++. The state which is furtherest down in the
* hierarchy, which have the timeoutAtEvent function implemented, will have
* the function called.
*/
virtual void timeoutAtEvent(void) = 0;
private:
StateMachineT* m_sm;

View File

@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
****************************************************************************/
#include <sys/time.h>
#include <cassert>
@ -132,23 +133,6 @@ class TcpPrioClientBase::Machine
ctx.connect_retry_wait.setRandomizePercent(p);
}
void setBgConnectMinTime(unsigned t)
{
ctx.bg_connect_retry_wait.setMinTime(t);
}
void setBgConnectMaxTime(unsigned t)
{
ctx.bg_connect_retry_wait.setMaxTime(t);
}
void setBgConnectBackoffPercent(unsigned p)
{
ctx.bg_connect_retry_wait.setBackoffPercent(p);
}
void setBgConnectRandomizePercent(unsigned p)
{
ctx.bg_connect_retry_wait.setRandomizePercent(p);
}
void setLookupParams(const std::string& label, DnsLookup::Type type)
{
ctx.dns.setLookupParams(label, DnsLookup::Type::SRV);
@ -228,7 +212,7 @@ class TcpPrioClientBase::Machine
operator Time() { return time(); }
private:
Time m_min_time = 2000;
Time m_min_time = 1000;
Time m_max_time = 20000;
Percent m_backoff = 50;
Percent m_randomize = 10;
@ -247,7 +231,6 @@ class TcpPrioClientBase::Machine
DnsSRVList rrs;
DnsSRVList::iterator next_rr = rrs.end();
BackoffTime connect_retry_wait;
BackoffTime bg_connect_retry_wait;
Context(TcpPrioClientBase *client)
: client(client), bg_con(client->newTcpClient()) {}
@ -443,6 +426,11 @@ class TcpPrioClientBase::Machine
setTimeout(ctx().connect_retry_wait);
}
void exit(void) noexcept
{
clearTimeout();
}
virtual void timeoutEvent(void) noexcept override
{
DEBUG_EVENT;
@ -493,11 +481,6 @@ class TcpPrioClientBase::Machine
: Async::StateBase<StateConnected, StateConnectedLowerPrio>
{
static constexpr auto NAME = "ConnectedLowerPrio";
void entry(void) noexcept
{
DEBUG_EVENT;
ctx().bg_connect_retry_wait.reset();
}
}; /* StateConnecting */
@ -508,10 +491,23 @@ class TcpPrioClientBase::Machine
void entry(void) noexcept
{
setTimeout(ctx().bg_connect_retry_wait.time());
struct timeval tv;
auto err = gettimeofday(&tv, NULL);
assert(err == 0);
struct tm tm;
time_t timeout_at = tv.tv_sec + 60;
auto tm_ret = localtime_r(&timeout_at, &tm);
assert(tm_ret == &tm);
tm.tm_sec = 0;
setTimeoutAt(tm, std::rand() % 500);
}
virtual void timeoutEvent(void) noexcept override
void exit(void) noexcept
{
clearTimeoutAt();
}
virtual void timeoutAtEvent(void) noexcept override
{
DEBUG_EVENT;
setState<StateConnectedLowerPrioSRVLookup>();
@ -683,30 +679,6 @@ void TcpPrioClientBase::setReconnectRandomizePercent(unsigned p)
}
void TcpPrioClientBase::setBgConnectMinTime(unsigned t)
{
m_machine->setBgConnectMinTime(t);
}
void TcpPrioClientBase::setBgConnectMaxTime(unsigned t)
{
m_machine->setBgConnectMaxTime(t);
}
void TcpPrioClientBase::setBgConnectBackoffPercent(unsigned p)
{
m_machine->setBgConnectBackoffPercent(p);
}
void TcpPrioClientBase::setBgConnectRandomizePercent(unsigned p)
{
m_machine->setBgConnectRandomizePercent(p);
}
void TcpPrioClientBase::setService(const std::string& srv_name,
const std::string& srv_proto,
const std::string& srv_domain)

View File

@ -169,30 +169,6 @@ class TcpPrioClientBase : public TcpClientBase
*/
void setReconnectRandomizePercent(unsigned p);
/**
* @brief Minimum time between background reconnects
* @param t Time in milliseconds
*/
void setBgConnectMinTime(unsigned t);
/**
* @brief Maximum time between background reconnects
* @param t Time in milliseconds
*/
void setBgConnectMaxTime(unsigned t);
/**
* @brief Percent to increase background reconnect time with each try
* @param p Percent
*/
void setBgConnectBackoffPercent(unsigned p);
/**
* @brief Percent to randomize background reconnect time
* @param p Percent
*/
void setBgConnectRandomizePercent(unsigned p);
/**
* @brief Use a DNS service resource record for connections
* @param srv_name The name of the service

View File

@ -181,14 +181,13 @@ bool CppDnsLookupWorker::doLookup(void)
m_notifier_watch.setFd(fd[0], FdWatch::FD_WATCH_RD);
m_notifier_watch.setEnabled(true);
ThreadContext ctx;
ctx.label = dns().label();
ctx.type = dns().type();
ctx.notifier_wr = fd[1];
ctx.anslen = 0;
ctx.thread_cerr.clear();
m_result = std::move(std::async(std::launch::async, workerFunc,
std::move(ctx)));
m_ctx = std::unique_ptr<ThreadContext>(new ThreadContext);
m_ctx->label = dns().label();
m_ctx->type = dns().type();
m_ctx->notifier_wr = fd[1];
m_ctx->anslen = 0;
m_ctx->thread_cerr.clear();
m_result = std::async(std::launch::async, workerFunc, std::ref(*m_ctx));
return true;
@ -199,13 +198,7 @@ void CppDnsLookupWorker::abortLookup(void)
{
if (m_result.valid())
{
const ThreadContext& ctx(m_result.get());
if (ctx.addrinfo != nullptr)
{
freeaddrinfo(ctx.addrinfo);
}
//m_result = std::move(std::future<ThreadContext>());
m_result.get();
}
int fd = m_notifier_watch.fd();
@ -214,6 +207,8 @@ void CppDnsLookupWorker::abortLookup(void)
m_notifier_watch.setFd(-1, FdWatch::FD_WATCH_RD);
close(fd);
}
m_ctx.reset();
} /* CppDnsLookupWorker::abortLookup */
@ -239,8 +234,7 @@ void CppDnsLookupWorker::abortLookup(void)
* Bugs:
*----------------------------------------------------------------------------
*/
CppDnsLookupWorker::ThreadContext CppDnsLookupWorker::workerFunc(
CppDnsLookupWorker::ThreadContext ctx)
void CppDnsLookupWorker::workerFunc(CppDnsLookupWorker::ThreadContext& ctx)
{
std::ostream& th_cerr = ctx.thread_cerr;
@ -343,8 +337,6 @@ CppDnsLookupWorker::ThreadContext CppDnsLookupWorker::workerFunc(
close(ctx.notifier_wr);
ctx.notifier_wr = -1;
return std::move(ctx);
} /* CppDnsLookupWorker::workerFunc */
@ -370,22 +362,22 @@ void CppDnsLookupWorker::notificationReceived(FdWatch *w)
close(w->fd());
w->setFd(-1, FdWatch::FD_WATCH_RD);
const ThreadContext& ctx(m_result.get());
m_result.get();
const std::string& thread_errstr = ctx.thread_cerr.str();
const std::string& thread_errstr = m_ctx->thread_cerr.str();
if (!thread_errstr.empty())
{
std::cerr << thread_errstr;
setLookupFailed();
}
if (ctx.type == DnsResourceRecord::Type::A)
if (m_ctx->type == DnsResourceRecord::Type::A)
{
if (ctx.addrinfo != nullptr)
if (m_ctx->addrinfo != nullptr)
{
struct addrinfo *entry;
std::vector<IpAddress> the_addresses;
for (entry = ctx.addrinfo; entry != 0; entry = entry->ai_next)
for (entry = m_ctx->addrinfo; entry != 0; entry = entry->ai_next)
{
IpAddress ip_addr(
reinterpret_cast<struct sockaddr_in*>(entry->ai_addr)->sin_addr);
@ -398,23 +390,23 @@ void CppDnsLookupWorker::notificationReceived(FdWatch *w)
{
the_addresses.push_back(ip_addr);
addResourceRecord(
new DnsResourceRecordA(ctx.label, 0, ip_addr));
new DnsResourceRecordA(m_ctx->label, 0, ip_addr));
}
}
freeaddrinfo(ctx.addrinfo);
m_ctx.reset();
}
}
else if (ctx.type == DnsResourceRecord::Type::PTR)
else if (m_ctx->type == DnsResourceRecord::Type::PTR)
{
if (ctx.host[0] != '\0')
if (m_ctx->host[0] != '\0')
{
addResourceRecord(
new DnsResourceRecordPTR(ctx.label, 0, ctx.host));
new DnsResourceRecordPTR(m_ctx->label, 0, m_ctx->host));
}
}
else
{
if (ctx.anslen == -1)
if (m_ctx->anslen == -1)
{
workerDone();
return;
@ -422,12 +414,12 @@ void CppDnsLookupWorker::notificationReceived(FdWatch *w)
char errbuf[256];
ns_msg msg;
int ret = ns_initparse(ctx.answer, ctx.anslen, &msg);
int ret = ns_initparse(m_ctx->answer, m_ctx->anslen, &msg);
if (ret == -1)
{
strerror_r(errno, errbuf, sizeof(errbuf));
std::cerr << "*** WARNING: ns_initparse failed (anslen="
<< ctx.anslen << "): " << errbuf << std::endl;
<< m_ctx->anslen << "): " << errbuf << std::endl;
setLookupFailed();
workerDone();
return;

View File

@ -169,12 +169,22 @@ class CppDnsLookupWorker : public DnsLookupWorker, public sigc::trackable
struct addrinfo* addrinfo = nullptr;
char host[NI_MAXHOST] = {0};
std::ostringstream thread_cerr;
~ThreadContext(void)
{
if (addrinfo != nullptr)
{
freeaddrinfo(addrinfo);
addrinfo = nullptr;
}
}
};
Async::FdWatch m_notifier_watch;
std::future<ThreadContext> m_result;
Async::FdWatch m_notifier_watch;
std::future<void> m_result;
std::unique_ptr<ThreadContext> m_ctx;
static ThreadContext workerFunc(ThreadContext ctx);
static void workerFunc(ThreadContext& ctx);
void notificationReceived(FdWatch *w);
}; /* class CppDnsLookupWorker */

View File

@ -8,10 +8,10 @@ QTEL=1.2.4.99.5
LIBECHOLIB=1.3.3.99.2
# Version for the Async library
LIBASYNC=1.6.99.21
LIBASYNC=1.6.99.22
# SvxLink versions
SVXLINK=1.7.99.67
SVXLINK=1.7.99.68
MODULE_HELP=1.0.0
MODULE_PARROT=1.1.1
MODULE_ECHO_LINK=1.5.99.3