rewrite Get Session Info to use new yielding D-Bus API
The new yielding API does not use try/catch, and has slightly different
parameters which makes the change look bigger than it is.
Tested:
Run ipmitool session info active
session handle : 1
slot count : 45
active sessions : 1
user id : 1
privilege level : ADMINISTRATOR
session type : IPMIv2/RMCP+
channel number : 0x01
console ip : 0.0.0.0
console mac : 00:00:00:00:00:00
console port : 54884
Console ip is reported as all zero due to a current netipmid bug.
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
Change-Id: Ia6574568c7f8863b3acffcf22e403c8be01d312a
diff --git a/apphandler.cpp b/apphandler.cpp
index 2430e8e..fdc2d67 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -1043,91 +1043,100 @@
return ipmi::ccSuccess;
}
-uint8_t getSessionState(std::shared_ptr<sdbusplus::asio::connection>& busp,
- const std::string& service, const std::string& objPath,
- uint8_t& sessionState)
+uint8_t getSessionState(ipmi::Context::ptr ctx, const std::string& service,
+ const std::string& objPath, uint8_t& sessionState)
{
- try
- {
- sessionState = std::get<uint8_t>(ipmi::getDbusProperty(
- *busp, service, objPath, session::sessionIntf, "State"));
- }
- catch (sdbusplus::exception::SdBusError& e)
+ boost::system::error_code ec = ipmi::getDbusProperty(
+ ctx, service, objPath, session::sessionIntf, "State", sessionState);
+ if (ec)
{
log<level::ERR>("Failed to fetch state property ",
entry("SERVICE=%s", service.c_str()),
entry("OBJECTPATH=%s", objPath.c_str()),
entry("INTERFACE=%s", session::sessionIntf),
- entry("ERRMSG=%s", e.what()));
+ entry("ERRMSG=%s", ec.message().c_str()));
return ipmi::ccUnspecifiedError;
}
-
return ipmi::ccSuccess;
}
static constexpr uint8_t macAddrLen = 6;
-struct GetSessionInfoRes
-{
- uint8_t sessionHandle;
- uint8_t totalSessionCount;
- uint8_t activeSessionCount;
- uint8_t userID;
- uint8_t privLevel;
- uint8_t channelNumber;
- uint32_t remoteIpAddr;
- std::array<uint8_t, macAddrLen> macAddr = {0};
- uint16_t remotePort;
-};
+/** Alias SessionDetails - contain the optional information about an
+ * RMCP+ session.
+ *
+ * @param userID - uint6_t session user ID (0-63)
+ * @param reserved - uint2_t reserved
+ * @param privilege - uint4_t session privilege (0-5)
+ * @param reserved - uint4_t reserved
+ * @param channel - uint4_t session channel number
+ * @param protocol - uint4_t session protocol
+ * @param remoteIP - uint32_t remote IP address
+ * @param macAddr - std::array<uint8_t, 6> mac address
+ * @param port - uint16_t remote port
+ */
+using SessionDetails =
+ std::tuple<uint2_t, uint6_t, uint4_t, uint4_t, uint4_t, uint4_t, uint32_t,
+ std::array<uint8_t, macAddrLen>, uint16_t>;
-uint8_t
- fillGetSessionInfoRes(std::shared_ptr<sdbusplus::asio::connection>& busp,
- const std::string& service,
- const std::string& objPath,
- struct GetSessionInfoRes& resp, uint8_t& sessionState)
+/** @brief get session details for a given session
+ *
+ * @param[in] ctx - ipmi::Context pointer for accessing D-Bus
+ * @param[in] service - D-Bus service name to fetch details from
+ * @param[in] objPath - D-Bus object path for session
+ * @param[out] sessionHandle - return session handle for session
+ * @param[out] sessionState - return session state for session
+ * @param[out] details - return a SessionDetails tuple containing other
+ * session info
+ * @return - ipmi::Cc success or error code
+ */
+ipmi::Cc getSessionDetails(ipmi::Context::ptr ctx, const std::string& service,
+ const std::string& objPath, uint8_t& sessionHandle,
+ uint8_t& sessionState, SessionDetails& details)
{
- try
- {
- ipmi::PropertyMap sessionProps = ipmi::getAllDbusProperties(
- *busp, service, objPath, session::sessionIntf);
+ ipmi::PropertyMap sessionProps;
+ boost::system::error_code ec = ipmi::getAllDbusProperties(
+ ctx, service, objPath, session::sessionIntf, sessionProps);
- sessionState = std::get<uint8_t>(sessionProps.at("State"));
- if (sessionState == static_cast<uint8_t>(session::State::active))
- {
- resp.sessionHandle =
- std::get<uint8_t>(sessionProps["SessionHandle"]);
- resp.userID = std::get<uint8_t>(sessionProps["UserID"]);
- resp.privLevel =
- std::get<uint8_t>(sessionProps["CurrentPrivilege"]);
- resp.channelNumber = std::get<uint8_t>(sessionProps["ChannelNum"]);
- resp.remoteIpAddr =
- std::get<uint32_t>(sessionProps["RemoteIPAddr"]);
- resp.remotePort = std::get<uint16_t>(sessionProps["RemotePort"]);
- }
- }
- catch (sdbusplus::exception::SdBusError& e)
+ if (ec)
{
log<level::ERR>("Failed to fetch state property ",
entry("SERVICE=%s", service.c_str()),
entry("OBJECTPATH=%s", objPath.c_str()),
entry("INTERFACE=%s", session::sessionIntf),
- entry("ERRMSG=%s", e.what()));
+ entry("ERRMSG=%s", ec.message().c_str()));
return ipmi::ccUnspecifiedError;
}
+ sessionState = ipmi::mappedVariant<uint8_t>(
+ sessionProps, "State", static_cast<uint8_t>(session::State::inactive));
+ if (sessionState == static_cast<uint8_t>(session::State::active))
+ {
+ sessionHandle =
+ ipmi::mappedVariant<uint8_t>(sessionProps, "SessionHandle", 0);
+ std::get<0>(details) =
+ ipmi::mappedVariant<uint8_t>(sessionProps, "UserID", 0xff);
+ // std::get<1>(details) = 0; // (default constructed to 0)
+ std::get<2>(details) =
+ ipmi::mappedVariant<uint8_t>(sessionProps, "CurrentPrivilege", 0);
+ // std::get<3>(details) = 0; // (default constructed to 0)
+ std::get<4>(details) =
+ ipmi::mappedVariant<uint8_t>(sessionProps, "ChannelNum", 0xff);
+ constexpr uint4_t rmcpPlusProtocol = 1;
+ std::get<5>(details) = rmcpPlusProtocol;
+ std::get<6>(details) =
+ ipmi::mappedVariant<uint32_t>(sessionProps, "RemoteIPAddr", 0);
+ // std::get<7>(details) = {{0}}; // default constructed to all 0
+ std::get<8>(details) =
+ ipmi::mappedVariant<uint16_t>(sessionProps, "RemotePort", 0);
+ }
+
return ipmi::ccSuccess;
}
-ipmi::RspType<
- uint8_t, // session handle,
- uint8_t, // total session count
- uint8_t, // active session count
- std::optional<std::tuple<uint8_t, // user ID
- uint8_t, // privilege level
- uint8_t, // channel number
- uint32_t, // remote ip address,
- std::array<uint8_t, macAddrLen>, // mac address
- uint16_t // remote port
- >>>
+ipmi::RspType<uint8_t, // session handle,
+ uint8_t, // total session count
+ uint8_t, // active session count
+ std::optional<SessionDetails>>
ipmiAppGetSessionInfo(ipmi::Context::ptr ctx, uint8_t sessionIndex,
ipmi::message::Payload& payload)
{
@@ -1143,87 +1152,77 @@
{
return ipmi::response(completionCode);
}
- struct GetSessionInfoRes res = {0};
- res.totalSessionCount = getTotalSessionCount();
- res.activeSessionCount = 0;
- auto busp = getSdBus();
-
- try
- {
- uint8_t index = 0;
- ipmi::ObjectTree objectTree = ipmi::getAllDbusObjects(
- *busp, session::sessionManagerRootPath, session::sessionIntf);
-
- for (auto& objectTreeItr : objectTree)
- {
- uint32_t sessionId = 0;
- uint8_t sessionHandle = session::defaultSessionHandle;
- std::string objectPath = objectTreeItr.first;
-
- if (!parseCloseSessionInputPayload(objectPath, sessionId,
- sessionHandle))
- {
- continue;
- }
- index++;
- auto& serviceMap = objectTreeItr.second;
- auto itr = serviceMap.begin();
-
- if (serviceMap.size() != 1)
- {
- return ipmi::responseUnspecifiedError();
- }
-
- std::string service = itr->first;
- uint8_t sessionState = 0;
- completionCode =
- getSessionState(busp, service, objectPath, sessionState);
- if (completionCode)
- {
- return ipmi::response(completionCode);
- }
-
- if (sessionState == static_cast<uint8_t>(session::State::active))
- {
- res.activeSessionCount++;
- }
-
- if (index != sessionIndex && reqSessionId != sessionId &&
- reqSessionHandle != sessionHandle)
- {
- continue;
- }
-
- completionCode =
- fillGetSessionInfoRes(busp, service, objectPath, res, state);
-
- if (completionCode)
- {
- return ipmi::response(completionCode);
- }
- }
- }
-
- catch (sdbusplus::exception::SdBusError& e)
+ ipmi::ObjectTree objectTree;
+ boost::system::error_code ec = ipmi::getAllDbusObjects(
+ ctx, session::sessionManagerRootPath, session::sessionIntf, objectTree);
+ if (ec)
{
log<level::ERR>("Failed to fetch object from dbus",
entry("INTERFACE=%s", session::sessionIntf),
- entry("ERRMSG=%s", e.what()));
+ entry("ERRMSG=%s", ec.message().c_str()));
return ipmi::responseUnspecifiedError();
}
- if (state == static_cast<uint8_t>(session::State::active))
+ uint8_t totalSessionCount = getTotalSessionCount();
+ uint8_t activeSessionCount = 0;
+ uint8_t sessionHandle = session::defaultSessionHandle;
+ std::optional<SessionDetails> maybeDetails;
+ uint8_t index = 0;
+ for (auto& objectTreeItr : objectTree)
{
- return ipmi::responseSuccess(
- res.sessionHandle, res.totalSessionCount, res.activeSessionCount,
- std::make_tuple(res.userID, res.privLevel, res.channelNumber,
- res.remoteIpAddr, res.macAddr, res.remotePort));
+ uint32_t sessionId = 0;
+ std::string objectPath = objectTreeItr.first;
+
+ if (!parseCloseSessionInputPayload(objectPath, sessionId,
+ sessionHandle))
+ {
+ continue;
+ }
+ index++;
+ auto& serviceMap = objectTreeItr.second;
+ auto itr = serviceMap.begin();
+
+ if (serviceMap.size() != 1)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+
+ std::string service = itr->first;
+ uint8_t sessionState = 0;
+ completionCode =
+ getSessionState(ctx, service, objectPath, sessionState);
+ if (completionCode)
+ {
+ return ipmi::response(completionCode);
+ }
+
+ if (sessionState == static_cast<uint8_t>(session::State::active))
+ {
+ activeSessionCount++;
+ }
+
+ if (index != sessionIndex && reqSessionId != sessionId &&
+ reqSessionHandle != sessionHandle)
+ {
+ continue;
+ }
+
+ SessionDetails details{};
+ completionCode = getSessionDetails(ctx, service, objectPath,
+ sessionHandle, state, details);
+
+ if (completionCode)
+ {
+ return ipmi::response(completionCode);
+ }
+ maybeDetails = std::move(details);
}
- else if (state == static_cast<uint8_t>(session::State::tearDownInProgress))
+
+ if (state == static_cast<uint8_t>(session::State::active) ||
+ state == static_cast<uint8_t>(session::State::tearDownInProgress))
{
- res.sessionHandle = 0;
- return ipmi::responseSuccess(res.sessionHandle, res.totalSessionCount,
- res.activeSessionCount, std::nullopt);
+ return ipmi::responseSuccess(sessionHandle, totalSessionCount,
+ activeSessionCount, maybeDetails);
}
return ipmi::responseInvalidFieldRequest();