Merge branch 'sm0svx:master' into svxreflector-authkey
This commit is contained in:
commit
4473d1aa2c
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue