summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVernon Mauery <vernon.mauery@linux.intel.com>2018-11-09 08:43:36 -0800
committerVernon Mauery <vernon.mauery@linux.intel.com>2019-02-01 13:01:18 -0800
commit7e4a651799df95e44b4c99825adf18a8ef878f52 (patch)
treed8ca0552f74bd860f3e0a112cf9eea57e616727b
parent7a0142c5298b13247614394ea707c1ea0502473d (diff)
downloadphosphor-net-ipmid-7e4a651799df95e44b4c99825adf18a8ef878f52.tar.gz
phosphor-net-ipmid-7e4a651799df95e44b4c99825adf18a8ef878f52.zip
netipmid: move sol console sockets to asio
Rewrite the SOL console sockets use boost::asio. This reduces code size and ties better into the main asio io loop. Change-Id: Ia79b9aa3fa3c7ce1ddd9b609b032160a88394f8c Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
-rw-r--r--main.cpp2
-rw-r--r--sd_event_loop.cpp83
-rw-r--r--sd_event_loop.hpp12
-rw-r--r--sol/sol_manager.cpp128
-rw-r--r--sol/sol_manager.hpp53
5 files changed, 87 insertions, 191 deletions
diff --git a/main.cpp b/main.cpp
index abb7958..1e35b9a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -29,7 +29,7 @@ static auto io = std::make_shared<boost::asio::io_context>();
session::Manager manager;
command::Table table;
eventloop::EventLoop loop(io);
-sol::Manager solManager;
+sol::Manager solManager(io);
std::tuple<session::Manager&, command::Table&, eventloop::EventLoop&,
sol::Manager&>
diff --git a/sd_event_loop.cpp b/sd_event_loop.cpp
index 990426f..8d24d23 100644
--- a/sd_event_loop.cpp
+++ b/sd_event_loop.cpp
@@ -61,50 +61,6 @@ void EventLoop::startRmcpReceive()
});
}
-static int consoleInputHandler(sd_event_source* es, int fd, uint32_t revents,
- void* userdata)
-{
- try
- {
- int readSize = 0;
-
- if (ioctl(fd, FIONREAD, &readSize) < 0)
- {
- log<level::ERR>("ioctl failed for FIONREAD:",
- entry("ERRNO=%d", errno));
- return 0;
- }
-
- std::vector<uint8_t> buffer(readSize);
- auto bufferSize = buffer.size();
- ssize_t readDataLen = 0;
-
- readDataLen = read(fd, buffer.data(), bufferSize);
-
- // Update the Console buffer with data read from the socket
- if (readDataLen > 0)
- {
- buffer.resize(readDataLen);
- std::get<sol::Manager&>(singletonPool).dataBuffer.write(buffer);
- }
- else if (readDataLen == 0)
- {
- log<level::ERR>("Connection Closed for host console socket");
- }
- else if (readDataLen < 0) // Error
- {
- log<level::ERR>("Reading from host console socket failed:",
- entry("ERRNO=%d", errno));
- }
- }
- catch (std::exception& e)
- {
- log<level::ERR>(e.what());
- }
-
- return 0;
-}
-
static int charAccTimerHandler(sd_event_source* s, uint64_t usec,
void* userdata)
{
@@ -223,45 +179,6 @@ int EventLoop::startEventLoop()
return EXIT_SUCCESS;
}
-void EventLoop::startHostConsole(const sol::CustomFD& fd)
-{
- int rc = 0;
-
- if ((fd() == -1) || hostConsole.get())
- {
- throw std::runtime_error("Console descriptor already added");
- }
-
- sd_event_source* source = nullptr;
-
- // Add the fd to the event loop for EPOLLIN
- rc = sd_event_add_io(event, &source, fd(), EPOLLIN, consoleInputHandler,
- nullptr);
- if (rc < 0)
- {
- throw std::runtime_error("Failed to add socket descriptor");
- }
-
- hostConsole.reset(source);
- source = nullptr;
-}
-
-void EventLoop::stopHostConsole()
-{
- if (hostConsole.get())
- {
- // Disable the host console payload
- int rc = sd_event_source_set_enabled(hostConsole.get(), SD_EVENT_OFF);
- if (rc < 0)
- {
- log<level::ERR>("Failed to disable the host console socket",
- entry("RC=%d", rc));
- }
-
- hostConsole.reset();
- }
-}
-
void EventLoop::startSOLPayloadInstance(uint8_t payloadInst,
IntervalType accumulateInterval,
IntervalType retryInterval)
diff --git a/sd_event_loop.hpp b/sd_event_loop.hpp
index c81218a..0d9c268 100644
--- a/sd_event_loop.hpp
+++ b/sd_event_loop.hpp
@@ -76,15 +76,6 @@ class EventLoop
*/
int startEventLoop();
- /** @brief Add host console I/O event source to the event loop.
- *
- * @param[in] fd - File descriptor for host console socket.
- */
- void startHostConsole(const sol::CustomFD& fd);
-
- /** @brief Remove host console I/O event source. */
- void stopHostConsole();
-
/** @brief Initialize the timers for the SOL payload instance
*
* This API would add the Character accumulate interval timer event
@@ -145,9 +136,6 @@ class EventLoop
/** @brief register the async handler for incoming udp packets */
void startRmcpReceive();
- /** @brief Event source object for host console. */
- EventSource hostConsole = nullptr;
-
/** @brief boost::asio io context to run with
*/
std::shared_ptr<boost::asio::io_context> io;
diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp
index 859f371..fc0efe9 100644
--- a/sol/sol_manager.cpp
+++ b/sol/sol_manager.cpp
@@ -6,6 +6,10 @@
#include <sys/socket.h>
#include <sys/un.h>
+#include <boost/asio/basic_stream_socket.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
+#include <boost/asio/write.hpp>
#include <chrono>
#include <cmath>
#include <phosphor-logging/log.hpp>
@@ -15,80 +19,78 @@ namespace sol
using namespace phosphor::logging;
-CustomFD::~CustomFD()
+void Manager::initConsoleSocket()
{
- if (fd >= 0)
- {
- // Remove the host console descriptor from the sd_event_loop
- std::get<eventloop::EventLoop&>(singletonPool).stopHostConsole();
- close(fd);
- }
+ // explicit length constructor for NUL-prefixed abstract path
+ std::string path(CONSOLE_SOCKET_PATH, CONSOLE_SOCKET_PATH_LEN);
+ boost::asio::local::stream_protocol::endpoint ep(path);
+ consoleSocket =
+ std::make_unique<boost::asio::local::stream_protocol::socket>(*io);
+ consoleSocket->connect(ep);
}
-void Manager::initHostConsoleFd()
+void Manager::consoleInputHandler()
{
- struct sockaddr_un addr;
- int rc = 0;
- int fd = 0;
-
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0)
+ boost::system::error_code ec;
+ boost::asio::socket_base::bytes_readable cmd(true);
+ consoleSocket->io_control(cmd, ec);
+ size_t readSize;
+ if (!ec)
{
- log<level::ERR>("Failed to open the host console socket",
- entry("ERRNO=%d", errno));
- throw std::runtime_error("Failed to open the host console socket");
+ readSize = cmd.get();
}
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- memcpy(&addr.sun_path, &CONSOLE_SOCKET_PATH, CONSOLE_SOCKET_PATH_LEN);
- consoleFD = std::make_unique<CustomFD>(fd);
- auto& conFD = *(consoleFD.get());
-
- rc =
- connect(conFD(), (struct sockaddr*)&addr,
- sizeof(addr) - sizeof(addr.sun_path) + CONSOLE_SOCKET_PATH_LEN);
- if (rc < 0)
+ else
+ {
+ log<level::ERR>("Reading ready count from host console socket failed:",
+ entry("EXCEPTION=%s", ec.message().c_str()));
+ return;
+ }
+ std::vector<uint8_t> buffer(readSize);
+ ec.clear();
+ size_t readDataLen =
+ consoleSocket->read_some(boost::asio::buffer(buffer), ec);
+ if (ec)
{
- log<level::ERR>("Failed to connect to host console socket address",
- entry("ERRNO=%d", errno));
- consoleFD.reset();
- throw std::runtime_error("Failed to connect to console server");
+ log<level::ERR>("Reading from host console socket failed:",
+ entry("EXCEPTION=%s", ec.message().c_str()));
+ return;
}
+
+ // Update the Console buffer with data read from the socket
+ buffer.resize(readDataLen);
+ dataBuffer.write(buffer);
}
int Manager::writeConsoleSocket(const std::vector<uint8_t>& input) const
{
- auto inBuffer = input.data();
- auto inBufferSize = input.size();
- size_t pos = 0;
- ssize_t rc = 0;
- int errVal = 0;
- auto& conFD = *(consoleFD.get());
-
- for (pos = 0; pos < inBufferSize; pos += rc)
+ boost::system::error_code ec;
+ boost::asio::write(*consoleSocket, boost::asio::buffer(input), ec);
+ return ec.value();
+}
+
+void Manager::startHostConsole()
+{
+ if (!consoleSocket)
{
- rc = write(conFD(), inBuffer + pos, inBufferSize - pos);
- if (rc <= 0)
- {
- if (errno == EINTR)
- {
- log<level::INFO>(" Retrying to handle EINTR",
- entry("ERRNO=%d", errno));
- rc = 0;
- continue;
- }
- else
- {
- errVal = errno;
- log<level::ERR>("Failed to write to host console socket",
- entry("ERRNO=%d", errno));
- return -errVal;
- }
- }
+ initConsoleSocket();
}
+ consoleSocket->async_wait(boost::asio::socket_base::wait_read,
+ [this](const boost::system::error_code& ec) {
+ if (!ec)
+ {
+ consoleInputHandler();
+ startHostConsole();
+ }
+ });
+}
- return 0;
+void Manager::stopHostConsole()
+{
+ if (consoleSocket)
+ {
+ consoleSocket->cancel();
+ consoleSocket.reset();
+ }
}
void Manager::startPayloadInstance(uint8_t payloadInstance,
@@ -96,11 +98,7 @@ void Manager::startPayloadInstance(uint8_t payloadInstance,
{
if (payloadMap.empty())
{
- initHostConsoleFd();
-
- // Register the fd in the sd_event_loop
- std::get<eventloop::EventLoop&>(singletonPool)
- .startHostConsole(*(consoleFD.get()));
+ startHostConsole();
}
// Create the SOL Context data for payload instance
@@ -132,7 +130,7 @@ void Manager::stopPayloadInstance(uint8_t payloadInstance)
if (payloadMap.empty())
{
- consoleFD.reset();
+ stopHostConsole();
dataBuffer.erase(dataBuffer.size());
}
diff --git a/sol/sol_manager.hpp b/sol/sol_manager.hpp
index 5a0c18c..5d96890 100644
--- a/sol/sol_manager.hpp
+++ b/sol/sol_manager.hpp
@@ -4,6 +4,8 @@
#include "session.hpp"
#include "sol_context.hpp"
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
#include <map>
#include <memory>
@@ -23,32 +25,6 @@ constexpr uint8_t retryIntervalFactor = 10;
using Instance = uint8_t;
-/** @struct CustomFD
- *
- * RAII wrapper for file descriptor.
- */
-struct CustomFD
-{
- CustomFD(const CustomFD&) = delete;
- CustomFD& operator=(const CustomFD&) = delete;
- CustomFD(CustomFD&&) = delete;
- CustomFD& operator=(CustomFD&&) = delete;
-
- CustomFD(int fd) : fd(fd)
- {
- }
-
- ~CustomFD();
-
- int operator()() const
- {
- return fd;
- }
-
- private:
- int fd = -1;
-};
-
using namespace std::chrono_literals;
/** @class Manager
@@ -65,13 +41,20 @@ class Manager
*/
using SOLPayloadMap = std::map<Instance, std::unique_ptr<Context>>;
- Manager() = default;
+ Manager() = delete;
~Manager() = default;
Manager(const Manager&) = delete;
Manager& operator=(const Manager&) = delete;
Manager(Manager&&) = default;
Manager& operator=(Manager&&) = default;
+ Manager(std::shared_ptr<boost::asio::io_context> io) : io(io)
+ {
+ }
+
+ /** @brief io context to add events to */
+ std::shared_ptr<boost::asio::io_context> io;
+
/** @brief Host Console Buffer. */
ConsoleData dataBuffer;
@@ -180,6 +163,12 @@ class Manager
*/
uint8_t channel = 1;
+ /** @brief Add host console I/O event source to the event loop. */
+ void startHostConsole();
+
+ /** @brief Remove host console I/O event source. */
+ void stopHostConsole();
+
/** @brief Start a SOL payload instance.
*
* Starting a payload instance involves creating the context object,
@@ -263,11 +252,15 @@ class Manager
private:
SOLPayloadMap payloadMap;
- /** @brief File descriptor for the host console. */
- std::unique_ptr<CustomFD> consoleFD = nullptr;
+ /** @brief Local stream socket for the host console. */
+ std::unique_ptr<boost::asio::local::stream_protocol::socket> consoleSocket =
+ nullptr;
/** @brief Initialize the host console file descriptor. */
- void initHostConsoleFd();
+ void initConsoleSocket();
+
+ /** @brief Handle incoming console data on the console socket */
+ void consoleInputHandler();
};
} // namespace sol
OpenPOWER on IntegriCloud