netipmid: move sol timers to asio
The IPMI SOL console was using sd_event-based timers directly (without
any abstraction). This moves to a much higher level abstraction that is
very easy to use: asio timers.
Change-Id: Id5df76a1918cdfae420e01884d664234810b7abd
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/sol/sol_context.cpp b/sol/sol_context.cpp
index fffb66f..215f725 100644
--- a/sol/sol_context.cpp
+++ b/sol/sol_context.cpp
@@ -8,9 +8,62 @@
namespace sol
{
-
using namespace phosphor::logging;
+Context::Context(std::shared_ptr<boost::asio::io_context> io,
+ uint8_t maxRetryCount, uint8_t sendThreshold, uint8_t instance,
+ session::SessionID sessionID) :
+ accumulateTimer(*io),
+ retryTimer(*io), maxRetryCount(maxRetryCount), retryCounter(maxRetryCount),
+ sendThreshold(sendThreshold), payloadInstance(instance),
+ sessionID(sessionID)
+{
+ session = std::get<session::Manager&>(singletonPool).getSession(sessionID);
+ enableAccumulateTimer(true);
+}
+
+void Context::enableAccumulateTimer(bool enable)
+{
+ // fetch the timeout from the SOL manager
+ std::chrono::microseconds interval =
+ std::get<sol::Manager&>(singletonPool).accumulateInterval;
+ if (enable)
+ {
+ accumulateTimer.expires_after(interval);
+ accumulateTimer.async_wait([this](const boost::system::error_code& ec) {
+ if (!ec)
+ {
+ charAccTimerHandler();
+ }
+ });
+ }
+ else
+ {
+ accumulateTimer.cancel();
+ }
+}
+
+void Context::enableRetryTimer(bool enable)
+{
+ if (enable)
+ {
+ // fetch the timeout from the SOL manager
+ std::chrono::microseconds interval =
+ std::get<sol::Manager&>(singletonPool).retryInterval;
+ retryTimer.expires_after(interval);
+ retryTimer.async_wait([this](const boost::system::error_code& ec) {
+ if (!ec)
+ {
+ retryTimerHandler();
+ }
+ });
+ }
+ else
+ {
+ retryTimer.cancel();
+ }
+}
+
void Context::processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum,
uint8_t count, bool status,
const std::vector<uint8_t>& input)
@@ -54,10 +107,8 @@
if (status || ((count != expectedCharCount) && ackSeqNum))
{
resendPayload(noClear);
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::RETRY, false);
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::RETRY, true);
+ enableRetryTimer(false);
+ enableRetryTimer(true);
return;
}
/*
@@ -70,8 +121,7 @@
std::get<sol::Manager&>(singletonPool).dataBuffer.erase(count);
// Once it is acknowledged stop the retry interval timer
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::RETRY, false);
+ enableRetryTimer(false);
retryCounter = maxRetryCount;
expectedCharCount = 0;
@@ -111,8 +161,7 @@
}
else
{
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, true);
+ enableAccumulateTimer(true);
}
}
@@ -123,8 +172,7 @@
/* Sent a ACK only response */
if (payloadCache.size() != 0 || (bufferSize < sendThreshold))
{
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, true);
+ enableAccumulateTimer(true);
std::vector<uint8_t> outPayload(sizeof(Payload));
auto response = reinterpret_cast<Payload*>(outPayload.data());
@@ -148,10 +196,8 @@
std::copy_n(handle, readSize, payloadCache.data() + sizeof(Payload));
expectedCharCount = readSize;
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::RETRY, true);
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, false);
+ enableRetryTimer(true);
+ enableAccumulateTimer(false);
sendPayload(payloadCache);
}
@@ -160,8 +206,7 @@
{
if (payloadCache.size() != 0)
{
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, true);
+ enableAccumulateTimer(true);
return -1;
}
@@ -179,10 +224,8 @@
std::copy_n(handle, readSize, payloadCache.data() + sizeof(Payload));
expectedCharCount = readSize;
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::RETRY, true);
- std::get<eventloop::EventLoop&>(singletonPool)
- .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, false);
+ enableRetryTimer(true);
+ enableAccumulateTimer(false);
sendPayload(payloadCache);
@@ -204,12 +247,54 @@
void Context::sendPayload(const std::vector<uint8_t>& out) const
{
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(sessionID);
-
message::Handler msgHandler(session->channelPtr, sessionID);
msgHandler.sendSOLPayload(out);
}
+void Context::charAccTimerHandler()
+{
+ auto bufferSize = std::get<sol::Manager&>(singletonPool).dataBuffer.size();
+
+ try
+ {
+ if (bufferSize > 0)
+ {
+ int rc = sendOutboundPayload();
+ if (rc == 0)
+ {
+ return;
+ }
+ }
+ enableAccumulateTimer(true);
+ }
+ catch (std::exception& e)
+ {
+ log<level::ERR>(e.what());
+ }
+}
+
+void Context::retryTimerHandler()
+{
+ try
+ {
+ if (retryCounter)
+ {
+ --retryCounter;
+ enableRetryTimer(true);
+ resendPayload(sol::Context::noClear);
+ }
+ else
+ {
+ retryCounter = maxRetryCount;
+ resendPayload(sol::Context::clear);
+ enableRetryTimer(false);
+ enableAccumulateTimer(true);
+ }
+ }
+ catch (std::exception& e)
+ {
+ log<level::ERR>(e.what());
+ }
+}
} // namespace sol