initial drop of phosphor-ipmi-blobs
This implements a majority of the OEM IPMI BLOBS protocol. The only
piece missing from this is the timed expiration of sessions.
Change-Id: I82c9d17b625c94fc3340edcfabbbf1ffeb5ad7ac
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/manager.hpp b/manager.hpp
new file mode 100644
index 0000000..cfa62f5
--- /dev/null
+++ b/manager.hpp
@@ -0,0 +1,254 @@
+#pragma once
+
+#include "blobs.hpp"
+
+#include <ctime>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace blobs
+{
+
+struct SessionInfo
+{
+ SessionInfo() = default;
+ SessionInfo(const std::string& path, GenericBlobInterface* handler,
+ uint16_t flags) :
+ blobId(path),
+ handler(handler), flags(flags)
+ {
+ }
+ ~SessionInfo() = default;
+
+ std::string blobId;
+ GenericBlobInterface* handler;
+ uint16_t flags;
+};
+
+class ManagerInterface
+{
+ public:
+ virtual ~ManagerInterface() = default;
+
+ virtual bool
+ registerHandler(std::unique_ptr<GenericBlobInterface> handler) = 0;
+
+ virtual uint32_t buildBlobList() = 0;
+
+ virtual std::string getBlobId(uint32_t index) = 0;
+
+ virtual bool open(uint16_t flags, const std::string& path,
+ uint16_t* session) = 0;
+
+ virtual bool stat(const std::string& path, struct BlobMeta* meta) = 0;
+
+ virtual bool stat(uint16_t session, struct BlobMeta* meta) = 0;
+
+ virtual bool commit(uint16_t session, const std::vector<uint8_t>& data) = 0;
+
+ virtual bool close(uint16_t session) = 0;
+
+ virtual std::vector<uint8_t> read(uint16_t session, uint32_t offset,
+ uint32_t requestedSize) = 0;
+
+ virtual bool write(uint16_t session, uint32_t offset,
+ const std::vector<uint8_t>& data) = 0;
+
+ virtual bool deleteBlob(const std::string& path) = 0;
+};
+
+/**
+ * Blob Manager used to store handlers and sessions.
+ */
+class BlobManager : public ManagerInterface
+{
+ public:
+ BlobManager()
+ {
+ next = static_cast<uint16_t>(std::time(nullptr));
+ };
+
+ ~BlobManager() = default;
+ /* delete copy constructor & assignment operator, only support move
+ * operations.
+ */
+ BlobManager(const BlobManager&) = delete;
+ BlobManager& operator=(const BlobManager&) = delete;
+ BlobManager(BlobManager&&) = default;
+ BlobManager& operator=(BlobManager&&) = default;
+
+ /**
+ * Register a handler. We own the pointer.
+ *
+ * @param[in] handler - a pointer to a blob handler.
+ * @return bool - true if registered.
+ */
+ bool
+ registerHandler(std::unique_ptr<GenericBlobInterface> handler) override;
+
+ /**
+ * Builds the blobId list for enumeration.
+ *
+ * @return lowest value returned is 0, otherwise the number of
+ * blobIds.
+ */
+ uint32_t buildBlobList() override;
+
+ /**
+ * Grabs the blobId for the indexed blobId.
+ *
+ * @param[in] index - the index into the blobId cache.
+ * @return string - the blobId or empty string on failure.
+ */
+ std::string getBlobId(uint32_t index) override;
+
+ /**
+ * Attempts to open the file specified and associates with a session.
+ *
+ * @param[in] flags - the flags to pass to open.
+ * @param[in] path - the file path to open.
+ * @param[in,out] session - pointer to store the session on success.
+ * @return bool - true if able to open.
+ */
+ bool open(uint16_t flags, const std::string& path,
+ uint16_t* session) override;
+
+ /**
+ * Attempts to retrieve a BlobMeta for the specified path.
+ *
+ * @param[in] path - the file path for stat().
+ * @param[in,out] meta - a pointer to store the metadata.
+ * @return bool - true if able to retrieve the information.
+ */
+ bool stat(const std::string& path, struct BlobMeta* meta) override;
+
+ /**
+ * Attempts to retrieve a BlobMeta for a given session.
+ *
+ * @param[in] session - the session for this command.
+ * @param[in,out] meta - a pointer to store the metadata.
+ * @return bool - true if able to retrieve the information.
+ */
+ bool stat(uint16_t session, struct BlobMeta* meta) override;
+
+ /**
+ * Attempt to commit a blob for a given session.
+ *
+ * @param[in] session - the session for this command.
+ * @param[in] data - an optional commit blob.
+ * @return bool - true if the commit succeeds.
+ */
+ bool commit(uint16_t session, const std::vector<uint8_t>& data) override;
+
+ /**
+ * Attempt to close a session. If the handler returns a failure
+ * in closing, the session is kept open.
+ *
+ * @param[in] session - the session for this command.
+ * @return bool - true if the session was closed.
+ */
+ bool close(uint16_t session) override;
+
+ /**
+ * Attempt to read bytes from the blob. If there's a failure, such as
+ * an invalid offset it'll just return 0 bytes.
+ *
+ * @param[in] session - the session for this command.
+ * @param[in] offset - the offset from which to read.
+ * @param[in] requestedSize - the number of bytes to try and read.
+ * @return the bytes read.
+ */
+ std::vector<uint8_t> read(uint16_t session, uint32_t offset,
+ uint32_t requestedSize) override;
+
+ /**
+ * Attempt to write to a blob. The manager does not track whether
+ * the session opened the file for writing.
+ *
+ * @param[in] session - the session for this command.
+ * @param[in] offset - the offset into the blob to write.
+ * @param[in] data - the bytes to write to the blob.
+ * @return bool - true if the write succeeded.
+ */
+ bool write(uint16_t session, uint32_t offset,
+ const std::vector<uint8_t>& data) override;
+
+ /**
+ * Attempt to delete a blobId. This method will just call the
+ * handler, which will return failure if the blob doesn't support
+ * deletion. This command will also fail if there are any open
+ * sessions against the specific blob.
+ *
+ * In the case where they specify a folder, such as /blob/skm where
+ * the "real" blobIds are /blob/skm/1, or /blob/skm/2, the manager
+ * may see there are on open sessions to that specific path and will
+ * call the handler. In this case, the handler is responsible for
+ * handling any checks or logic.
+ *
+ * @param[in] path - the blobId path.
+ * @return bool - true if delete was successful.
+ */
+ bool deleteBlob(const std::string& path) override;
+
+ /**
+ * Attempts to return a valid unique session id.
+ *
+ * @param[in,out] - pointer to the session.
+ * @return bool - true if able to allocate.
+ */
+ bool getSession(uint16_t* session);
+
+ /**
+ * Given a file path will return first handler to answer that it owns
+ * it.
+ *
+ * @param[in] path - the file path.
+ * @return pointer to the handler or nullptr if not found.
+ */
+ GenericBlobInterface* getHandler(const std::string& path);
+
+ /**
+ * Given a session id will return associated handler.
+ *
+ * @param[in] session - the session.
+ * @return pointer to the handler or nullptr if not found.
+ */
+ GenericBlobInterface* getHandler(uint16_t session);
+
+ /**
+ * Given a session id will return associated metadata, including
+ * the handler and the flags passed into open.
+ *
+ * @param[in] session - the session.
+ * @return pointer to the information or nullptr if not found.
+ */
+ SessionInfo* getSessionInfo(uint16_t session);
+
+ /**
+ * Given a session id will return associated path.
+ *
+ * @param[in] session - the session.
+ * @return the path or "" on failure.
+ */
+ std::string getPath(uint16_t session) const;
+
+ private:
+ void incrementOpen(const std::string& path);
+ void decrementOpen(const std::string& path);
+ int getOpen(const std::string& path) const;
+
+ /* The next session ID to use */
+ uint16_t next;
+ /* Temporary list of blobIds used for enumeration. */
+ std::vector<std::string> ids;
+ /* List of Blob handler. */
+ std::vector<std::unique_ptr<GenericBlobInterface>> handlers;
+ /* Mapping of session ids to blob handlers and the path used with open.
+ */
+ std::unordered_map<uint16_t, SessionInfo> sessions;
+ /* Mapping of open blobIds */
+ std::unordered_map<std::string, int> openFiles;
+};
+} // namespace blobs