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