537483687468 2024-08-23 15:13 采纳率: 20%
浏览 9

bmcweb的console如何设置成多路sol??

bmcweb里面obmc_console.hpp的源码如下所示:

#pragma once
#include "app.hpp"
#include "async_resp.hpp"
#include "websocket.hpp"
#include <sys/socket.h>

#include <boost/asio/local/stream_protocol.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/system/error_code.hpp>

#include <array>
#include <memory>
#include <string>
#include <string_view>

namespace crow
{
namespace obmc_console
{

// Update this value each time we add new console route.
static constexpr const uint maxSessions = 32;

class ConsoleHandler : public std::enable_shared_from_this<ConsoleHandler>
{
  public:
    ConsoleHandler(boost::asio::io_context& ioc,
                   crow::websocket::Connection& connIn) :
        hostSocket(ioc), conn(connIn)
    {}

    ~ConsoleHandler() = default;

    ConsoleHandler(const ConsoleHandler&) = delete;
    ConsoleHandler(ConsoleHandler&&) = delete;
    ConsoleHandler& operator=(const ConsoleHandler&) = delete;
    ConsoleHandler& operator=(ConsoleHandler&&) = delete;

    void doWrite()
    {
        if (doingWrite)
        {
            BMCWEB_LOG_DEBUG("Already writing.  Bailing out");
            return;
        }

        if (inputBuffer.empty())
        {
            BMCWEB_LOG_DEBUG("Outbuffer empty.  Bailing out");
            return;
        }

        doingWrite = true;
        hostSocket.async_write_some(
            boost::asio::buffer(inputBuffer.data(), inputBuffer.size()),
            [weak(weak_from_this())](const boost::beast::error_code& ec,
                                     std::size_t bytesWritten) {
                std::shared_ptr<ConsoleHandler> self = weak.lock();
                if (self == nullptr)
                {
                    return;
                }

                self->doingWrite = false;
                self->inputBuffer.erase(0, bytesWritten);
                if (ec == boost::asio::error::eof)
                {
                    self->conn.close("Error in reading to host port");
                    return;
                }
                if (ec)
                {
                    BMCWEB_LOG_ERROR("Error in host serial write {}",
                                     ec.message());
                    return;
                }
                self->doWrite();
            });
    }

    static void afterSendEx(const std::weak_ptr<ConsoleHandler>& weak)
    {
        std::shared_ptr<ConsoleHandler> self = weak.lock();
        if (self == nullptr)
        {
            return;
        }
        self->doRead();
    }

    void doRead()
    {
        BMCWEB_LOG_DEBUG("Reading from socket");
        hostSocket.async_read_some(
            boost::asio::buffer(outputBuffer),
            [this, weakSelf(weak_from_this())](
                const boost::system::error_code& ec, std::size_t bytesRead) {
                BMCWEB_LOG_DEBUG("read done.  Read {} bytes", bytesRead);
                std::shared_ptr<ConsoleHandler> self = weakSelf.lock();
                if (self == nullptr)
                {
                    return;
                }
                if (ec)
                {
                    BMCWEB_LOG_ERROR("Couldn't read from host serial port: {}",
                                     ec.message());
                    conn.close("Error connecting to host port");
                    return;
                }
                std::string_view payload(outputBuffer.data(), bytesRead);
                self->conn.sendEx(
                    crow::websocket::MessageType::Binary, payload,
                    std::bind_front(afterSendEx, weak_from_this()));
            });
    }

    bool connect(int fd)
    {
        boost::system::error_code ec;
        boost::asio::local::stream_protocol proto;
        hostSocket.assign(proto, fd, ec);
        if (ec)
        {
            BMCWEB_LOG_ERROR(
                "Failed to assign the DBUS socket Socket assign error: {}",
                ec.message());
            return false;
        }
        conn.resumeRead();
        doWrite();
        doRead();
        return true;
    }

    boost::asio::local::stream_protocol::socket hostSocket;
    std::array<char, 4096> outputBuffer{};
    std::string inputBuffer;
    bool doingWrite = false;
    crow::websocket::Connection& conn;
};

using ObmcConsoleMap = boost::container::flat_map<
    crow::websocket::Connection*, std::shared_ptr<ConsoleHandler>, std::less<>,
    std::vector<std::pair<crow::websocket::Connection*,
                          std::shared_ptr<ConsoleHandler>>>>;

inline ObmcConsoleMap& getConsoleHandlerMap()
{
    static ObmcConsoleMap map;
    return map;
}

// Remove connection from the connection map and if connection map is empty
// then remove the handler from handlers map.
inline void onClose(crow::websocket::Connection& conn, const std::string& err)
{
    BMCWEB_LOG_INFO("Closing websocket. Reason: {}", err);
    auto iter = getConsoleHandlerMap().find(&conn);
    if (iter == getConsoleHandlerMap().end())
    {
        BMCWEB_LOG_CRITICAL("Unable to find connection {}", logPtr(&conn));
        return;
    }
    BMCWEB_LOG_DEBUG("Remove connection {} from obmc console", logPtr(&conn));
    // Removed last connection so remove the path
    getConsoleHandlerMap().erase(iter);
}

inline void connectConsoleSocket(crow::websocket::Connection& conn,
                                 const boost::system::error_code& ec,
                                 const sdbusplus::message::unix_fd& unixfd)
{
    if (ec)
    {
        BMCWEB_LOG_ERROR(
            "Failed to call console Connect() method DBUS error: {}",
            ec.message());
        conn.close("Failed to connect");
        return;
    }

    // Look up the handler
    auto iter = getConsoleHandlerMap().find(&conn);
    if (iter == getConsoleHandlerMap().end())
    {
        BMCWEB_LOG_ERROR("Connection was already closed");
        return;
    }

    int fd = dup(unixfd);
    if (fd == -1)
    {
        BMCWEB_LOG_ERROR("Failed to dup the DBUS unixfd error: {}",
                         strerror(errno));
        conn.close("Internal error");
        return;
    }
    BMCWEB_LOG_DEBUG("Console duped FD: {}", fd);
    if (!iter->second->connect(fd))
    {
        close(fd);
        conn.close("Internal Error");
    }
}

inline void processConsoleObject(
    crow::websocket::Connection& conn, const std::string& consoleObjPath,
    const boost::system::error_code& ec,
    const ::dbus::utility::MapperGetObject& objInfo)
{
    // Look up the handler
    auto iter = getConsoleHandlerMap().find(&conn);
    if (iter == getConsoleHandlerMap().end())
    {
        BMCWEB_LOG_ERROR("Connection was already closed");
        return;
    }
    if (ec)
    {
        BMCWEB_LOG_WARNING("getDbusObject() for consoles failed. DBUS error:{}",
                           ec.message());
        conn.close("getDbusObject() for consoles failed.");
        return;
    }

    const auto valueIface = objInfo.begin();
    if (valueIface == objInfo.end())
    {
        BMCWEB_LOG_WARNING("getDbusObject() returned unexpected size: {}",
                           objInfo.size());
        conn.close("getDbusObject() returned unexpected size");
        return;
    }

    const std::string& consoleService = valueIface->first;
    BMCWEB_LOG_DEBUG("Looking up unixFD for Service {} Path {}", consoleService,
                     consoleObjPath);
    // Call Connect() method to get the unix FD
    crow::connections::systemBus->async_method_call(
        [&conn](const boost::system::error_code& ec1,
                const sdbusplus::message::unix_fd& unixfd) {
            connectConsoleSocket(conn, ec1, unixfd);
        },
        consoleService, consoleObjPath, "xyz.openbmc_project.Console.Access",
        "Connect");
}

// Query consoles from DBUS and find the matching to the
// rules string.
inline void onOpen(crow::websocket::Connection& conn)
{
    std::string consoleLeaf;
    BMCWEB_LOG_DEBUG("Connection {} opened", logPtr(&conn));
    if (getConsoleHandlerMap().size() >= maxSessions)
    {
        conn.close("Max sessions are already connected");
        return;
    }

    std::shared_ptr<ConsoleHandler> handler =
        std::make_shared<ConsoleHandler>(conn.getIoContext(), conn);
    getConsoleHandlerMap().emplace(&conn, handler);

    conn.deferRead();

    // Keep old path for backward compatibility
    if (conn.url().path() == "/console0")
    {
        consoleLeaf = "default";
    }
    else
    {
        // Get the console id from console router path and prepare the console
        // object path and console service.
        consoleLeaf = conn.url().segments().back();
    }
    std::string consolePath =
        sdbusplus::message::object_path("/xyz/openbmc_project/console") /
        consoleLeaf;

    BMCWEB_LOG_DEBUG("Console Object path = {} Request target = {}",
                     consolePath, conn.url().path());

    // mapper call lambda
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Console.Access"};

    dbus::utility::getDbusObject(
        consolePath, interfaces,
        [&conn, consolePath](const boost::system::error_code& ec,
                             const ::dbus::utility::MapperGetObject& objInfo) {
            processConsoleObject(conn, consolePath, ec, objInfo);
        });
}

inline void onMessage(crow::websocket::Connection& conn,
                      const std::string& data, bool /*isBinary*/)
{
    auto handler = getConsoleHandlerMap().find(&conn);
    if (handler == getConsoleHandlerMap().end())
    {
        BMCWEB_LOG_CRITICAL("Unable to find connection {}", logPtr(&conn));
        return;
    }
    handler->second->inputBuffer += data;
    handler->second->doWrite();
}

inline void requestRoutes(App& app)
{
    BMCWEB_ROUTE(app, "/console0")
        .privileges({{"OpenBMCHostConsole"}})
        .websocket()
        .onopen(onOpen)
        .onclose(onClose)
        .onmessage(onMessage);

    BMCWEB_ROUTE(app, "/console/<str>")
        .privileges({{"OpenBMCHostConsole"}})
        .websocket()
        .onopen(onOpen)
        .onclose(onClose)
        .onmessage(onMessage);
}
} // namespace obmc_console
} // namespace crow

如果bmcweb和多路主机相连,即需要操作多个console,openbmc该如何配置对应的uart,保证不同的路由 BMCWEB_ROUTE(app, "/console/")选择不同的uart连接到指定的主机

  • 写回答

1条回答 默认 最新

  • 吃不了席 2024-08-23 17:14
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    为了实现这个需求,我们需要对代码进行一些修改。首先,我们需要在ConsoleHandler类中添加一个成员变量来存储当前的UART连接。然后,我们需要修改connect()方法,使其能够根据不同的路由选择不同的UART连接。最后,我们需要修改onOpen()方法,使其能够将路由信息传递给ConsoleHandler对象。

    以下是修改后的代码:

    // 在ConsoleHandler类中添加一个成员变量来存储当前的UART连接
    class ConsoleHandler : public std::enable_shared_from_this<ConsoleHandler>
    {
      // ...
      std::shared_ptr<UARTConnection> uartConnection; // 添加这一行
      // ...
    };
    
    // 修改connect()方法,使其能够根据不同的路由选择不同的UART连接
    bool ConsoleHandler::connect(int fd, const std::string& route) // 修改这一行
    {
      boost::system::error_code ec;
      boost::asio::local::stream_protocol proto;
      hostSocket.assign(proto, fd, ec);
      if (ec)
      {
        BMCWEB_LOG_ERROR(
            "Failed to assign the DBUS socket Socket assign error: {}",
            ec.message());
        return false;
      }
      conn.resumeRead();
      doWrite();
      doRead();
    
      // 根据路由信息选择不同的UART连接
      if (route == "/console0")
      {
        uartConnection = std::make_shared<UARTConnection>(uart0);
      }
      else if (route == "/console/1")
      {
        uartConnection = std::make_shared<UARTConnection>(uart1);
      }
      // 添加更多的路由和UART连接对应关系
      // ...
      else
      {
        BMCWEB_LOG_ERROR("Invalid route: {}", route);
        return false;
      }
    
      return true;
    }
    
    // 修改onOpen()方法,使其能够将路由信息传递给ConsoleHandler对象
    inline void onOpen(crow::websocket::Connection& conn, const std::string& route) // 修改这一行
    {
      // ...
      std::shared_ptr<ConsoleHandler> handler =
          std::make_shared<ConsoleHandler>(conn.getIoContext(), conn, route); // 修改这一行
      // ...
    }
    

    这样,当不同的路由连接到Web服务器时,它们将使用不同的UART连接与主机进行通信。

    评论

报告相同问题?

问题事件

  • 创建了问题 8月23日

悬赏问题

  • ¥15 有关wireshark抓包的问题
  • ¥15 需要写计算过程,不要写代码,求解答,数据都在图上
  • ¥15 向数据表用newid方式插入GUID问题
  • ¥15 multisim电路设计
  • ¥20 用keil,写代码解决两个问题,用库函数
  • ¥50 ID中开关量采样信号通道、以及程序流程的设计
  • ¥15 U-Mamba/nnunetv2固定随机数种子
  • ¥15 vba使用jmail发送邮件正文里面怎么加图片
  • ¥15 vb6.0如何向数据库中添加自动生成的字段数据。
  • ¥20 在easyX库下编写C语言扑克游戏跑的快,能实现简单的人机对战