| #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 |