/* 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);
    ssize_t r = read(ipmbi2cSlaveFd, buffer.data(), ipmbMaxFrameLength);

    // Handle error cases.
    if (r < 0)
    {
        goto end;
    }

    /* 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;
}
