blob: e58ccc954eed217227e55b1959ab8d56fbde6081 [file] [log] [blame] [edit]
#pragma once
#include "base.hpp"
#include "platform.hpp"
#include "pldmd/handler.hpp"
#include <libpldm/file.h>
#include <fstream>
#include <functional>
#include <map>
#include <string>
#include <string_view>
namespace pldm
{
namespace responder
{
namespace file_transfer
{
struct FileDescriptor
{
FILE* fp;
pldm_tid_t tid;
uint32_t index;
uint32_t fileSize;
uint32_t startingOffset;
uint32_t sectionLength;
uint32_t sentLength;
uint32_t prevChecksum;
uint16_t fileIdentifier;
};
/**
* @brief Reads a specified portion of a file
*
* @param fp An open file pointer.
* @param fileSize The total size of the file in bytes.
* @param offset The starting position from where to read in the file stream.
* @param readSize The number of bytes to read from the offset.
* @param data_ptr Pointer to the buffer to store data. At minimum buffer size
* should be readSize.
* @return 0 if successful else -1.
*/
int fileRead(FILE* fp, uint32_t fileSize, uint32_t offset, uint32_t readSize,
uint8_t* dataPtr);
class Handler : public CmdHandler
{
public:
Handler(responder::base::Handler* baseHandler,
responder::platform::Handler* platformHandler);
private:
/**
* @brief Returns a free file descriptor
*/
std::optional<uint16_t> getFreeFileDescriptor();
/**
* @brief Removes a file descriptor from fileDescriptors
*/
void removeFileDescriptor(uint16_t fileDescriptor);
/**
* @brief Handler for the DfOpen command
*/
Response dfOpen(pldm_tid_t tid, const pldm_msg* request,
size_t payloadLength);
/**
* @brief Handler for the DfClose command
*/
Response dfClose(pldm_tid_t tid, const pldm_msg* request,
size_t payloadLength);
/**
* @brief Calculates the data length and transfer flag for a DfRead response
*/
uint32_t getDataLengthBytesAndTransferFlag(
const FileDescriptor& fileDescriptor, uint32_t currOffset,
uint16_t multipartSize, uint8_t* transferFlag);
/**
* @brief Calculates the next offset for a DfRead response
*/
uint32_t getNextOffset(uint32_t currOffset, uint32_t dataLengthBytes);
/**
* @brief Creates a DfRead response message
*/
Response createReadResponse(
const pldm_msg* request,
const pldm_base_multipart_receive_req& decodedReq,
FileDescriptor& fileDescriptor, uint32_t currentTransferHandle,
uint8_t transferFlag, uint32_t nextTransferHandle,
uint32_t dataLengthBytes);
/**
* @brief Handles the first part of a DfRead transfer
*/
Response dfReadTransferFirstPart(
const pldm_msg* request,
const pldm_base_multipart_receive_req& decodedReq,
uint16_t multipartSize, FileDescriptor& fileDescriptor);
/**
* @brief Handles the current or next part of a DfRead transfer
*/
Response dfReadTransferCurrentOrNextPart(
const pldm_msg* request,
const pldm_base_multipart_receive_req& decodedReq,
uint16_t multipartSize, FileDescriptor& fileDescriptor);
/**
* @brief Handles the completion or abort of a DfRead transfer
*/
Response dfReadTransferCompleteOrAbort(
const pldm_msg* request,
const pldm_base_multipart_receive_req& decodedReq,
uint16_t multipartSize, FileDescriptor& fileDescriptor);
/**
* @brief Handler for the DfRead command
*/
Response dfRead(pldm_tid_t tid, const pldm_msg* request,
size_t payloadLength);
Response handleMultipartReceive(pldm_tid_t tid, const pldm_msg* request,
size_t reqMsgLen) override;
responder::base::Handler* baseHandler;
// PLDM Platform type handler. File pointers will be initialized during file
// PDR descriptor handling. So This will allow the file transfer handler to
// get the FILE pointers from platform handler.
responder::platform::Handler* platformHandler;
// Store active file descriptors
std::map<uint16_t, FileDescriptor> fileDescriptors;
// This value will be incremented each time a new file descriptor is
// created. This is the simplest approach. We could change this later if we
// need a better approach.
uint16_t nextFileDescriptor;
};
} // namespace file_transfer
} // namespace responder
} // namespace pldm