/* Copyright 2018 Intel
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "ipmbbridged.hpp"

#include "ipmbdefines.hpp"
#include "ipmbutils.hpp"

#include <boost/algorithm/string/replace.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/write.hpp>
#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>

#include <filesystem>
#include <fstream>
#include <list>
#include <tuple>
#include <unordered_map>

/**
 * @brief Dbus
 */
static constexpr const char* ipmbBus = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
static constexpr const char* ipmbObj = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
static constexpr const char* ipmbDbusIntf = "org.openbmc.Ipmb";

boost::asio::io_context io;
auto conn = std::make_shared<sdbusplus::asio::connection>(io);

static std::list<IpmbChannel> ipmbChannels;
static const std::unordered_map<std::string, ipmbChannelType>
    ipmbChannelTypeMap = {{"me", ipmbChannelType::me},
                          {"ipmb", ipmbChannelType::ipmb}};

/**
 * @brief Ipmb request class methods
 */
IpmbRequest::IpmbRequest()
{
    data.reserve(ipmbMaxDataSize);
}

IpmbRequest::IpmbRequest(uint8_t address, uint8_t netFn, uint8_t rsLun,
                         uint8_t rqSA, uint8_t seq, uint8_t rqLun, uint8_t cmd,
                         const std::vector<uint8_t>& inputData) :
    address(address),
    netFn(netFn), rsLun(rsLun), rqSA(rqSA), seq(seq), rqLun(rqLun), cmd(cmd),
    timer(io)
{
    data.reserve(ipmbMaxDataSize);
    state = ipmbRequestState::invalid;

    if (inputData.size() > 0)
    {
        data = std::move(inputData);
    }
}

void IpmbRequest::i2cToIpmbConstruct(IPMB_HEADER* ipmbBuffer,
                                     size_t bufferLength)
{
    // constructing ipmb request from i2c buffer
    netFn = ipmbNetFnGet(ipmbBuffer->Header.Req.rsNetFnLUN);
    rsLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Req.rsNetFnLUN);
    rqSA = ipmbBuffer->Header.Req.rqSA;
    seq = ipmbSeqGet(ipmbBuffer->Header.Req.rqSeqLUN);
    rqLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Req.rqSeqLUN);
    cmd = ipmbBuffer->Header.Req.cmd;

    size_t dataLength = bufferLength -
                        (ipmbConnectionHeaderLength +
                         ipmbRequestDataHeaderLength + ipmbChecksumSize);

    if (dataLength > 0)
    {
        data.insert(data.end(), ipmbBuffer->Header.Req.data,
                    &ipmbBuffer->Header.Req.data[dataLength]);
    }
}

int IpmbRequest::ipmbToi2cConstruct(std::vector<uint8_t>& buffer)
{
    /* Add one byte for length byte as per required by driver */
    size_t bufferLength = 1 + data.size() + ipmbRequestDataHeaderLength +
                          ipmbConnectionHeaderLength + ipmbChecksumSize;

    if (bufferLength > ipmbMaxFrameLength)
    {
        return -1;
    }

    buffer.resize(bufferLength);
    static_assert(ipmbMaxFrameLength >= sizeof(IPMB_HEADER));
    IPMB_PKT* ipmbPkt = reinterpret_cast<IPMB_PKT*>(buffer.data());
    ipmbPkt->len = bufferLength - 1;
    IPMB_HEADER* ipmbBuffer = &(ipmbPkt->hdr);

    // constructing buffer from ipmb request
    ipmbBuffer->Header.Req.address = address;
    ipmbBuffer->Header.Req.rsNetFnLUN = ipmbNetFnLunSet(netFn, rsLun);
    ipmbBuffer->Header.Req.rqSA = rqSA;
    ipmbBuffer->Header.Req.rqSeqLUN = ipmbSeqLunSet(seq, rqLun);
    ipmbBuffer->Header.Req.cmd = cmd;

    ipmbBuffer->Header.Req.checksum1 = ipmbChecksumCompute(
        (uint8_t*)ipmbBuffer, ipmbConnectionHeaderLength - ipmbChecksumSize);

    if (data.size() > 0)
    {
        std::copy(data.begin(), data.end(), ipmbBuffer->Header.Req.data);
    }

    buffer[bufferLength - ipmbChecksumSize] =
        ipmbChecksumCompute((uint8_t*)ipmbBuffer + ipmbChecksum2StartOffset,
                            (ipmbRequestDataHeaderLength + data.size()));

    return 0;
}

std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
    IpmbRequest::returnMatchedResponse()
{
    return std::make_tuple(
        static_cast<int>(ipmbResponseStatus::success), matchedResponse->netFn,
        matchedResponse->rsLun, matchedResponse->cmd,
        matchedResponse->completionCode, matchedResponse->data);
}

static std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
    returnStatus(ipmbResponseStatus status)
{
    // we only want to send status here, other fields are not relevant
    return std::make_tuple(static_cast<int>(status), 0, 0, 0, 0,
                           std::vector<uint8_t>(0));
}

/**
 * @brief Ipmb response class methods
 */
IpmbResponse::IpmbResponse()
{
    data.reserve(ipmbMaxDataSize);
}

IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
                           uint8_t rsSA, uint8_t seq, uint8_t rsLun,
                           uint8_t cmd, uint8_t completionCode,
                           const std::vector<uint8_t>& inputData) :
    address(address),
    netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
    completionCode(completionCode)
{
    data.reserve(ipmbMaxDataSize);

    if (inputData.size() > 0)
    {
        data = std::move(inputData);
    }
}

void IpmbResponse::i2cToIpmbConstruct(IPMB_HEADER* ipmbBuffer,
                                      size_t bufferLength)
{
    netFn = ipmbNetFnGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
    rqLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
    rsSA = ipmbBuffer->Header.Resp.rsSA;
    seq = ipmbSeqGet(ipmbBuffer->Header.Resp.rsSeqLUN);
    rsLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Resp.rsSeqLUN);
    cmd = ipmbBuffer->Header.Resp.cmd;
    completionCode = ipmbBuffer->Header.Resp.completionCode;

    size_t dataLength = bufferLength -
                        (ipmbConnectionHeaderLength +
                         ipmbResponseDataHeaderLength + ipmbChecksumSize);

    if (dataLength > 0)
    {
        data.insert(data.end(), ipmbBuffer->Header.Resp.data,
                    &ipmbBuffer->Header.Resp.data[dataLength]);
    }
}

std::shared_ptr<std::vector<uint8_t>> IpmbResponse::ipmbToi2cConstruct()
{
    /* Add one byte for length byte as per required by driver */
    size_t bufferLength = 1 + data.size() + ipmbResponseDataHeaderLength +
                          ipmbConnectionHeaderLength + ipmbChecksumSize;

    if (bufferLength > ipmbMaxFrameLength)
    {
        return nullptr;
    }

    std::shared_ptr<std::vector<uint8_t>> buffer =
        std::make_shared<std::vector<uint8_t>>(bufferLength);

    IPMB_PKT* ipmbPkt = reinterpret_cast<IPMB_PKT*>(buffer->data());
    ipmbPkt->len = bufferLength - 1;
    IPMB_HEADER* ipmbBuffer = &(ipmbPkt->hdr);

    ipmbBuffer->Header.Resp.address = address;
    ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
    ipmbBuffer->Header.Resp.rsSA = rsSA;
    ipmbBuffer->Header.Resp.rsSeqLUN = ipmbSeqLunSet(seq, rsLun);
    ipmbBuffer->Header.Resp.cmd = cmd;
    ipmbBuffer->Header.Resp.completionCode = completionCode;

    ipmbBuffer->Header.Resp.checksum1 = ipmbChecksumCompute(
        (uint8_t*)ipmbBuffer, ipmbConnectionHeaderLength - ipmbChecksumSize);

    if (data.size() > 0)
    {
        std::copy(data.begin(), data.end(), ipmbBuffer->Header.Resp.data);
    }

    (*buffer)[bufferLength - ipmbChecksumSize] =
        ipmbChecksumCompute((uint8_t*)ipmbBuffer + ipmbChecksum2StartOffset,
                            (ipmbResponseDataHeaderLength + data.size()));

    return buffer;
}

bool IpmbCommandFilter::isBlocked(const uint8_t reqNetFn, const uint8_t cmd)
{
    auto blockedCmd = unhandledCommands.find({reqNetFn, cmd});

    if (blockedCmd != unhandledCommands.end())
    {
        return true;
    }

    return false;
}

void IpmbCommandFilter::addFilter(const uint8_t reqNetFn, const uint8_t cmd)
{
    if (unhandledCommands.insert({reqNetFn, cmd}).second)
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "addFilter: added command to filter",
            phosphor::logging::entry("netFn = %d", reqNetFn),
            phosphor::logging::entry("cmd = %d", cmd));
    }
}

/**
 * @brief Ipmb channel
 */
void IpmbChannel::ipmbSendI2cFrame(std::shared_ptr<std::vector<uint8_t>> buffer,
                                   size_t retriesAttempted = 0)
{
    IPMB_PKT* ipmbPkt = reinterpret_cast<IPMB_PKT*>(buffer->data());
    uint8_t targetAddr = ipmbIsResponse(&(ipmbPkt->hdr))
                             ? ipmbPkt->hdr.Header.Resp.address
                             : ipmbPkt->hdr.Header.Req.address;
    boost::asio::async_write(
        i2cSlaveDescriptor, boost::asio::buffer(*buffer),
        [this, buffer, retriesAttempted,
         targetAddr](const boost::system::error_code& ec, size_t bytesSent) {
        if (ec)
        {
            size_t currentRetryCnt = retriesAttempted;

            if (currentRetryCnt > ipmbI2cNumberOfRetries)
            {
                std::string msgToLog =
                    "ipmbSendI2cFrame: send to I2C failed after retries."
                    " busId=" +
                    std::to_string(ipmbBusId) +
                    ", targetAddr=" + std::to_string(targetAddr) +
                    ", error=" + ec.message();
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    msgToLog.c_str());
                return;
            }
            currentRetryCnt++;
            ipmbSendI2cFrame(buffer, currentRetryCnt);
        }
        });
}

/**
 * @brief Ipmb Outstanding Requests
 */
void IpmbChannel::makeRequestInvalid(IpmbRequest& request)
{
    // change request state to invalid and remove it from outstanding requests
    // list
    request.state = ipmbRequestState::invalid;
    outstandingRequests[request.seq] = nullptr;
}

void IpmbChannel::makeRequestValid(std::shared_ptr<IpmbRequest> request)
{
    // change request state to valid and add it to outstanding requests list
    request->state = ipmbRequestState::valid;
    outstandingRequests[request->seq] = request;
}

bool IpmbChannel::seqNumGet(uint8_t& seq)
{
    static uint8_t seqNum = 0;

    for (int i = 0; i < ipmbMaxOutstandingRequestsCount; i++)
    {
        seqNum = (seqNum + 1) % ipmbMaxOutstandingRequestsCount;

        if (outstandingRequests[seqNum] == nullptr)
        {
            seq = seqNum;
            return true;
        }
    }

    return false;
}

void IpmbChannel::responseMatch(std::unique_ptr<IpmbResponse>& response)
{
    std::shared_ptr<IpmbRequest> request = outstandingRequests[response->seq];

    if (request != nullptr)
    {
        if (((ipmbRespNetFn(request->netFn)) == (response->netFn)) &&
            ((request->rqLun) == (response->rqLun)) &&
            ((request->rsLun) == (response->rsLun)) &&
            ((request->cmd) == (response->cmd)))
        {
            // match, response is corresponding to previously sent request
            request->state = ipmbRequestState::matched;
            request->timer->cancel();
            request->matchedResponse = std::move(response);
        }
    }
}

void IpmbChannel::processI2cEvent()
{
    std::array<uint8_t, ipmbMaxFrameLength> buffer{};
    IPMB_PKT* ipmbPkt = reinterpret_cast<IPMB_PKT*>(buffer.data());
    IPMB_HEADER* ipmbFrame = &(ipmbPkt->hdr);

    lseek(ipmbi2cSlaveFd, 0, SEEK_SET);
    int r = read(ipmbi2cSlaveFd, buffer.data(), ipmbMaxFrameLength);

    /* Substract first byte len size from total frame length */
    r--;

    if ((r < ipmbMinFrameLength) || (r > ipmbMaxFrameLength))
    {
        goto end;
    }

    // valiate the frame
    if (!isFrameValid(ipmbFrame, r))
    {
        goto end;
    }

    // if it is message received from ipmb channel, send out dbus signal
    if (getChannelType() == ipmbChannelType::ipmb)
    {
        auto ipmbMessageReceived = IpmbRequest();
        ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);
        sdbusplus::message_t msg = conn->new_signal(ipmbObj, ipmbDbusIntf,
                                                    "receiveBroadcast");
        msg.append(ipmbMessageReceived.netFn, ipmbMessageReceived.cmd,
                   ipmbMessageReceived.data);
        msg.signal_send();
    }

    // copy frame to ipmib message buffer
    if (ipmbIsResponse(ipmbFrame))
    {
        std::unique_ptr<IpmbResponse> ipmbMessageReceived =
            std::make_unique<IpmbResponse>();

        ipmbMessageReceived->i2cToIpmbConstruct(ipmbFrame, r);

        // try to match response with outstanding request
        responseMatch(ipmbMessageReceived);
    }
    else
    {
        // if command is blocked - respond with 'invalid command'
        // completion code
        if (commandFilter)
        {
            uint8_t netFn = ipmbNetFnGet(ipmbFrame->Header.Req.rsNetFnLUN);
            uint8_t cmd = ipmbFrame->Header.Req.cmd;
            uint8_t rqSA = ipmbFrame->Header.Req.rqSA;

            if (commandFilter->isBlocked(netFn, cmd))
            {
                uint8_t seq = ipmbSeqGet(ipmbFrame->Header.Req.rqSeqLUN);
                uint8_t lun =
                    ipmbLunFromSeqLunGet(ipmbFrame->Header.Req.rqSeqLUN);

                // prepare generic response
                auto ipmbResponse = IpmbResponse(
                    rqSA, ipmbRespNetFn(netFn), lun, ipmbBmcSlaveAddress, seq,
                    ipmbRsLun, cmd, ipmbIpmiInvalidCmd, {});

                auto buffer = ipmbResponse.ipmbToi2cConstruct();
                if (buffer)
                {
                    ipmbSendI2cFrame(buffer);
                }

                goto end;
            }
        }

        auto ipmbMessageReceived = IpmbRequest();
        ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);

        int devId = getDevIndex();

        std::map<std::string, std::variant<int>> options{
            {"rqSA", ipmbAddressTo7BitSet(ipmbMessageReceived.rqSA)},
            {"hostId", devId}};

        using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
                                           std::vector<uint8_t>>;
        conn->async_method_call(
            [this, rqLun{ipmbMessageReceived.rqLun},
             seq{ipmbMessageReceived.seq}, address{ipmbMessageReceived.rqSA}](
                const boost::system::error_code& ec,
                const IpmiDbusRspType& response) {
            const auto& [netfn, lun, cmd, cc, payload] = response;
            if (ec)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "processI2cEvent: error getting response from IPMI");
                return;
            }

            uint8_t bmcSlaveAddress = getBmcSlaveAddress();

            if (payload.size() > ipmbMaxDataSize)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "processI2cEvent: response exceeding maximum size");

                // prepare generic response
                auto ipmbResponse = IpmbResponse(
                    address, netfn, rqLun, bmcSlaveAddress, seq, ipmbRsLun, cmd,
                    ipmbIpmiCmdRespNotProvided, {});

                auto buffer = ipmbResponse.ipmbToi2cConstruct();
                if (buffer)
                {
                    ipmbSendI2cFrame(buffer);
                }

                return;
            }

            if (!(netfn & ipmbNetFnResponseMask))
            {
                // we are not expecting request here
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "processI2cEvent: got a request instead of response");
                return;
            }

            // if command is not supported, add it to filter
            if (cc == ipmbIpmiInvalidCmd)
            {
                addFilter(ipmbReqNetFnFromRespNetFn(netfn), cmd);
            }

            // payload is empty after constructor invocation
            auto ipmbResponse = IpmbResponse(address, netfn, rqLun,
                                             bmcSlaveAddress, seq, lun, cmd, cc,
                                             payload);

            auto buffer = ipmbResponse.ipmbToi2cConstruct();
            if (!buffer)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "processI2cEvent: error constructing a request");
                return;
            }

            ipmbSendI2cFrame(buffer);
            },
            "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
            "xyz.openbmc_project.Ipmi.Server", "execute",
            ipmbMessageReceived.netFn, ipmbMessageReceived.rsLun,
            ipmbMessageReceived.cmd, ipmbMessageReceived.data, options);
    }

end:
    i2cSlaveDescriptor.async_wait(
        boost::asio::posix::descriptor_base::wait_read,
        [this](const boost::system::error_code& ec) {
        if (ec)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Error: processI2cEvent()");
            return;
        }

        processI2cEvent();
        });
}

IpmbChannel::IpmbChannel(boost::asio::io_context& io,
                         uint8_t ipmbBmcSlaveAddress,
                         uint8_t ipmbRqSlaveAddress, uint8_t channelIdx,
                         std::shared_ptr<IpmbCommandFilter> commandFilter) :
    i2cSlaveDescriptor(io),
    ipmbBmcSlaveAddress(ipmbBmcSlaveAddress),
    ipmbRqSlaveAddress(ipmbRqSlaveAddress), channelIdx(channelIdx),
    commandFilter(commandFilter)
{}

int IpmbChannel::ipmbChannelInit(const char* ipmbI2cSlave)
{
    // extract bus id from slave path and save
    std::string ipmbI2cSlaveStr(ipmbI2cSlave);
    auto findHyphen = ipmbI2cSlaveStr.find("-");
    std::string busStr = ipmbI2cSlaveStr.substr(findHyphen + 1);
    try
    {
        ipmbBusId = std::stoi(busStr);
    }
    catch (const std::invalid_argument&)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "ipmbChannelInit: invalid bus id in slave-path config");
        return -1;
    }

    // Check if sysfs has device. If not, enable I2C slave driver by command
    // echo "ipmb-dev 0x1010" > /sys/bus/i2c/devices/i2c-0/new_device
    bool hasSysfs = std::filesystem::exists(ipmbI2cSlave);
    if (!hasSysfs)
    {
        std::string deviceFileName = "/sys/bus/i2c/devices/i2c-" + busStr +
                                     "/new_device";
        std::string para = "ipmb-dev 0x1010"; // init with BMC addr 0x20
        std::fstream deviceFile;
        deviceFile.open(deviceFileName, std::ios::out);
        if (!deviceFile.good())
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "ipmbChannelInit: error opening deviceFile");
            return -1;
        }
        deviceFile << para;
        deviceFile.close();
    }

    // open fd to i2c slave device for read write
    ipmbi2cSlaveFd = open(ipmbI2cSlave, O_RDWR | O_NONBLOCK | O_CLOEXEC);
    if (ipmbi2cSlaveFd < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "ipmbChannelInit: error opening ipmbI2cSlave");
        return -1;
    }

    i2cSlaveDescriptor.assign(ipmbi2cSlaveFd);

    i2cSlaveDescriptor.async_wait(
        boost::asio::posix::descriptor_base::wait_read,
        [this](const boost::system::error_code& ec) {
        if (ec)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Error: processI2cEvent()");
            return;
        }

        processI2cEvent();
        });

    return 0;
}

int IpmbChannel::ipmbChannelUpdateSlaveAddress(const uint8_t newBmcSlaveAddr)
{
    if (ipmbi2cSlaveFd > 0)
    {
        i2cSlaveDescriptor.close();
        close(ipmbi2cSlaveFd);
        ipmbi2cSlaveFd = 0;
    }

    // disable old I2C slave driver by command:
    //     echo "0x1010" > /sys/bus/i2c/devices/i2c-0/delete_device
    std::string deviceFileName;
    std::string para;
    std::fstream deviceFile;
    deviceFileName = "/sys/bus/i2c/devices/i2c-" + std::to_string(ipmbBusId) +
                     "/delete_device";
    para = "0x1010"; // align with removed ipmb0 definition in dts file
    deviceFile.open(deviceFileName, std::ios::out);
    if (!deviceFile.good())
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "ipmbChannelUpdateSlaveAddress: error opening deviceFile to delete "
            "sysfs");
        return -1;
    }
    deviceFile << para;
    deviceFile.close();

    // enable new I2C slave driver by command:
    //      echo "ipmb-dev 0x1012" > /sys/bus/i2c/devices/i2c-0/new_device
    deviceFileName = "/sys/bus/i2c/devices/i2c-" + std::to_string(ipmbBusId) +
                     "/new_device";
    std::ostringstream hex;
    uint16_t addr = 0x1000 + (newBmcSlaveAddr >> 1);
    hex << std::hex << static_cast<uint16_t>(addr);
    const std::string& addressHexStr = hex.str();
    para = "ipmb-dev 0x" + addressHexStr;
    deviceFile.open(deviceFileName, std::ios::out);
    if (!deviceFile.good())
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "ipmbChannelUpdateSlaveAddress: error opening deviceFile to create "
            "sysfs");
        return -1;
    }
    deviceFile << para;
    deviceFile.close();

    // open fd to i2c slave device
    std::string ipmbI2cSlaveStr = "/dev/ipmb-" + std::to_string(ipmbBusId);
    ipmbi2cSlaveFd = open(ipmbI2cSlaveStr.c_str(), O_RDWR | O_NONBLOCK);
    if (ipmbi2cSlaveFd < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "ipmbChannelInit: error opening ipmbI2cSlave");
        return -1;
    }

    // start to receive i2c data as slave
    i2cSlaveDescriptor.assign(ipmbi2cSlaveFd);
    i2cSlaveDescriptor.async_wait(
        boost::asio::posix::descriptor_base::wait_read,
        [this](const boost::system::error_code& ec) {
        if (ec)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Error: processI2cEvent()");
            return;
        }

        processI2cEvent();
        });

    ipmbBmcSlaveAddress = newBmcSlaveAddr;

    return 0;
}

uint8_t IpmbChannel::getBusId()
{
    return ipmbBusId;
}

uint8_t IpmbChannel::getBmcSlaveAddress()
{
    return ipmbBmcSlaveAddress;
}

uint8_t IpmbChannel::getRqSlaveAddress()
{
    return ipmbRqSlaveAddress;
}

uint8_t IpmbChannel::getDevIndex()
{
    return channelIdx >> 2;
}

uint8_t IpmbChannel::getChannelIdx()
{
    return channelIdx;
}

ipmbChannelType IpmbChannel::getChannelType()
{
    return static_cast<ipmbChannelType>((channelIdx & 3));
}

void IpmbChannel::addFilter(const uint8_t respNetFn, const uint8_t cmd)
{
    if (commandFilter)
    {
        commandFilter->addFilter(respNetFn, cmd);
    }
}

std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
    IpmbChannel::requestAdd(boost::asio::yield_context& yield,
                            std::shared_ptr<IpmbRequest> request)
{
    makeRequestValid(request);

    std::vector<uint8_t> buffer(0);
    if (request->ipmbToi2cConstruct(buffer) != 0)
    {
        return returnStatus(ipmbResponseStatus::error);
    }

    for (int i = 0; i < ipmbNumberOfTries; i++)
    {
        boost::system::error_code ec;
        int i2cRetryCnt = 0;

        for (; i2cRetryCnt < ipmbI2cNumberOfRetries; i2cRetryCnt++)
        {
            boost::asio::async_write(i2cSlaveDescriptor,
                                     boost::asio::buffer(buffer), yield[ec]);

            if (ec)
            {
                continue; // retry
            }
            break;
        }

        if (i2cRetryCnt == ipmbI2cNumberOfRetries)
        {
            std::string msgToLog =
                "requestAdd: Sent to I2C failed after retries."
                " busId=" +
                std::to_string(ipmbBusId) + ", error=" + ec.message();
            phosphor::logging::log<phosphor::logging::level::INFO>(
                msgToLog.c_str());
        }

        request->timer->expires_after(
            std::chrono::milliseconds(ipmbRequestRetryTimeout));
        request->timer->async_wait(yield[ec]);

        if (ec && ec != boost::asio::error::operation_aborted)
        {
            // unexpected error - invalidate request and return generic error
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "requestAdd: async_wait error");
            makeRequestInvalid(*request);
            return returnStatus(ipmbResponseStatus::error);
        }

        if (request->state == ipmbRequestState::matched)
        {
            // matched response, send it to client application
            makeRequestInvalid(*request);
            return request->returnMatchedResponse();
        }
    }

    makeRequestInvalid(*request);
    return returnStatus(ipmbResponseStatus::timeout);
}

static IpmbChannel* getChannel(uint8_t reqChannel)
{
    auto channel = std::find_if(ipmbChannels.begin(), ipmbChannels.end(),
                                [reqChannel](IpmbChannel& channel) {
        return channel.getChannelIdx() == reqChannel;
    });
    if (channel != ipmbChannels.end())
    {
        return &(*channel);
    }

    return nullptr;
}

static int initializeChannels()
{
    std::shared_ptr<IpmbCommandFilter> commandFilter =
        std::make_shared<IpmbCommandFilter>();

    constexpr const char* configFilePath =
        "/usr/share/ipmbbridge/ipmb-channels.json";
    std::ifstream configFile(configFilePath);
    if (!configFile.is_open())
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "initializeChannels: Cannot open config path");
        return -1;
    }
    try
    {
        uint8_t devIndex = 0;
        auto data = nlohmann::json::parse(configFile, nullptr);
        for (const auto& channelConfig : data["channels"])
        {
            const std::string& typeConfig = channelConfig["type"];
            const std::string& slavePath = channelConfig["slave-path"];
            uint8_t bmcAddr = channelConfig["bmc-addr"];
            uint8_t reqAddr = channelConfig["remote-addr"];

            ipmbChannelType type = ipmbChannelTypeMap.at(typeConfig);

            if (channelConfig.contains("devIndex"))
            {
                devIndex = channelConfig["devIndex"];
            }

            auto channel = ipmbChannels.emplace(
                ipmbChannels.end(), io, bmcAddr, reqAddr,
                ((devIndex << 2) | static_cast<uint8_t>(type)), commandFilter);
            if (channel->ipmbChannelInit(slavePath.c_str()) < 0)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "initializeChannels: channel initialization failed");
                return -1;
            }
        }
    }
    catch (const nlohmann::json::exception& e)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "initializeChannels: Error parsing config file");
        return -1;
    }
    catch (const std::out_of_range& e)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "initializeChannels: Error invalid type");
        return -1;
    }
    return 0;
}

auto ipmbHandleRequest = [](boost::asio::yield_context yield,
                            uint8_t reqChannel, uint8_t netfn, uint8_t lun,
                            uint8_t cmd, std::vector<uint8_t> dataReceived) {
    IpmbChannel* channel = getChannel(reqChannel);

    if (channel == nullptr)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "ipmbHandleRequest: requested channel does not exist");
        return returnStatus(ipmbResponseStatus::invalid_param);
    }

    // check outstanding request list for valid sequence number
    uint8_t seqNum = 0;
    bool seqValid = channel->seqNumGet(seqNum);
    if (!seqValid)
    {
        phosphor::logging::log<phosphor::logging::level::WARNING>(
            "ipmbHandleRequest: cannot add more requests to the list");
        return returnStatus(ipmbResponseStatus::busy);
    }

    uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
    uint8_t rqSlaveAddress = channel->getRqSlaveAddress();

    // construct the request to add it to outstanding request list
    std::shared_ptr<IpmbRequest> request = std::make_shared<IpmbRequest>(
        rqSlaveAddress, netfn, ipmbRsLun, bmcSlaveAddress, seqNum, lun, cmd,
        dataReceived);

    if (!request->timer)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "ipmbHandleRequest: timer object does not exist");
        return returnStatus(ipmbResponseStatus::error);
    }

    return channel->requestAdd(yield, request);
};

void addUpdateSlaveAddrHandler()
{
    // callback to handle dbus signal of updating slave addr
    std::function<void(sdbusplus::message_t&)> updateSlaveAddrHandler =
        [](sdbusplus::message_t& message) {
        uint8_t reqChannel, busId, slaveAddr;

        // valid source of signal, check whether from multi-node manager
        std::string pathName = message.get_path();
        if (pathName != "/xyz/openbmc_project/MultiNode/Status")
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "addUpdateSlaveAddrHandler: invalid obj path");
            return;
        }

        message.read(reqChannel, busId, slaveAddr);

        IpmbChannel* channel = getChannel(reqChannel);

        if (channel == nullptr ||
            channel->getChannelType() != ipmbChannelType::ipmb)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "addUpdateSlaveAddrHandler: invalid channel");
            return;
        }
        if (busId != channel->getBusId())
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "addUpdateSlaveAddrHandler: invalid busId");
            return;
        }
        if (channel->getBmcSlaveAddress() == slaveAddr)
        {
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "addUpdateSlaveAddrHandler: channel bmc slave addr is "
                "unchanged, do nothing");
            return;
        }

        channel->ipmbChannelUpdateSlaveAddress(slaveAddr);
    };

    static auto match = std::make_unique<sdbusplus::bus::match_t>(
        static_cast<sdbusplus::bus_t&>(*conn),
        "type='signal',member='updateBmcSlaveAddr',", updateSlaveAddrHandler);
}

void addSendBroadcastHandler()
{
    // callback to handle dbus signal of sending broadcast message
    std::function<void(sdbusplus::message_t&)> sendBroadcastHandler =
        [](sdbusplus::message_t& message) {
        uint8_t reqChannel, netFn, lun, cmd;
        std::vector<uint8_t> dataReceived;
        message.read(reqChannel, netFn, lun, cmd, dataReceived);

        IpmbChannel* channel = getChannel(reqChannel);

        if (channel == nullptr)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "addSendBroadcastMsgHandler: requested channel does not "
                "exist");
            return;
        }

        uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
        uint8_t seqNum = 0; // seqNum is not used in broadcast msg
        uint8_t targetAddr = broadcastAddress;

        std::shared_ptr<IpmbRequest> request = std::make_shared<IpmbRequest>(
            targetAddr, netFn, ipmbRsLun, bmcSlaveAddress, seqNum, lun, cmd,
            dataReceived);

        std::shared_ptr<std::vector<uint8_t>> buffer =
            std::make_shared<std::vector<uint8_t>>();

        if (request->ipmbToi2cConstruct(*buffer) != 0)
        {
            return;
        }

        channel->ipmbSendI2cFrame(buffer);
    };

    static auto match = std::make_unique<sdbusplus::bus::match_t>(
        static_cast<sdbusplus::bus_t&>(*conn),
        "type='signal',member='sendBroadcast',", sendBroadcastHandler);
}

/**
 * @brief Main
 */
int main(int argc, char* argv[])
{
    conn->request_name(ipmbBus);

    auto server = sdbusplus::asio::object_server(conn);

    std::shared_ptr<sdbusplus::asio::dbus_interface> ipmbIface =
        server.add_interface(ipmbObj, ipmbDbusIntf);

    ipmbIface->register_method("sendRequest", std::move(ipmbHandleRequest));
    ipmbIface->initialize();

    if (initializeChannels() < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Error initializeChannels");
        return -1;
    }

    addUpdateSlaveAddrHandler();

    addSendBroadcastHandler();

    io.run();
    return 0;
}
