1 #pragma once 2 3 #include <blobs-ipmid/blobs.hpp> 4 #include <chrono> 5 #include <ctime> 6 #include <ipmid/oemrouter.hpp> 7 #include <memory> 8 #include <string> 9 #include <unordered_map> 10 #include <vector> 11 12 namespace blobs 13 { 14 15 /* The maximum read size. 16 * NOTE: Once this can be dynamically determined, we'll switch to that method. 17 * Having this in a header allows it to used cleanly for now. 18 */ 19 const int crcSize = sizeof(uint16_t); 20 const int btReplyHdrLen = 5; 21 const int btTransportLength = 64; 22 const uint32_t maximumReadSize = 23 btTransportLength - (btReplyHdrLen + oem::groupMagicSize + crcSize); 24 25 struct SessionInfo 26 { 27 SessionInfo() = default; 28 SessionInfo(const std::string& path, GenericBlobInterface* handler, 29 uint16_t flags) : 30 blobId(path), 31 handler(handler), flags(flags) 32 { 33 } 34 ~SessionInfo() = default; 35 36 std::string blobId; 37 GenericBlobInterface* handler; 38 uint16_t flags; 39 40 /* Initially set during open(). read/write/writeMeta/commit/stat operations 41 * would update it. 42 */ 43 std::chrono::time_point<std::chrono::steady_clock> lastActionTime = 44 std::chrono::steady_clock::now(); 45 }; 46 47 class ManagerInterface 48 { 49 public: 50 virtual ~ManagerInterface() = default; 51 52 virtual bool 53 registerHandler(std::unique_ptr<GenericBlobInterface> handler) = 0; 54 55 virtual uint32_t buildBlobList() = 0; 56 57 virtual std::string getBlobId(uint32_t index) = 0; 58 59 virtual bool open(uint16_t flags, const std::string& path, 60 uint16_t* session) = 0; 61 62 virtual bool stat(const std::string& path, BlobMeta* meta) = 0; 63 64 virtual bool stat(uint16_t session, BlobMeta* meta) = 0; 65 66 virtual bool commit(uint16_t session, const std::vector<uint8_t>& data) = 0; 67 68 virtual bool close(uint16_t session) = 0; 69 70 virtual std::vector<uint8_t> read(uint16_t session, uint32_t offset, 71 uint32_t requestedSize) = 0; 72 73 virtual bool write(uint16_t session, uint32_t offset, 74 const std::vector<uint8_t>& data) = 0; 75 76 virtual bool deleteBlob(const std::string& path) = 0; 77 78 virtual bool writeMeta(uint16_t session, uint32_t offset, 79 const std::vector<uint8_t>& data) = 0; 80 }; 81 82 /** 83 * Blob Manager used to store handlers and sessions. 84 */ 85 class BlobManager : public ManagerInterface 86 { 87 public: 88 BlobManager() 89 { 90 next = static_cast<uint16_t>(std::time(nullptr)); 91 }; 92 93 ~BlobManager() = default; 94 /* delete copy constructor & assignment operator, only support move 95 * operations. 96 */ 97 BlobManager(const BlobManager&) = delete; 98 BlobManager& operator=(const BlobManager&) = delete; 99 BlobManager(BlobManager&&) = default; 100 BlobManager& operator=(BlobManager&&) = default; 101 102 /** 103 * Register a handler. We own the pointer. 104 * 105 * @param[in] handler - a pointer to a blob handler. 106 * @return bool - true if registered. 107 */ 108 bool 109 registerHandler(std::unique_ptr<GenericBlobInterface> handler) override; 110 111 /** 112 * Builds the blobId list for enumeration. 113 * 114 * @return lowest value returned is 0, otherwise the number of 115 * blobIds. 116 */ 117 uint32_t buildBlobList() override; 118 119 /** 120 * Grabs the blobId for the indexed blobId. 121 * 122 * @param[in] index - the index into the blobId cache. 123 * @return string - the blobId or empty string on failure. 124 */ 125 std::string getBlobId(uint32_t index) override; 126 127 /** 128 * Attempts to open the file specified and associates with a session. 129 * 130 * @param[in] flags - the flags to pass to open. 131 * @param[in] path - the file path to open. 132 * @param[in,out] session - pointer to store the session on success. 133 * @return bool - true if able to open. 134 */ 135 bool open(uint16_t flags, const std::string& path, 136 uint16_t* session) override; 137 138 /** 139 * Attempts to retrieve a BlobMeta for the specified path. 140 * 141 * @param[in] path - the file path for stat(). 142 * @param[in,out] meta - a pointer to store the metadata. 143 * @return bool - true if able to retrieve the information. 144 */ 145 bool stat(const std::string& path, BlobMeta* meta) override; 146 147 /** 148 * Attempts to retrieve a BlobMeta for a given session. 149 * 150 * @param[in] session - the session for this command. 151 * @param[in,out] meta - a pointer to store the metadata. 152 * @return bool - true if able to retrieve the information. 153 */ 154 bool stat(uint16_t session, BlobMeta* meta) override; 155 156 /** 157 * Attempt to commit a blob for a given session. 158 * 159 * @param[in] session - the session for this command. 160 * @param[in] data - an optional commit blob. 161 * @return bool - true if the commit succeeds. 162 */ 163 bool commit(uint16_t session, const std::vector<uint8_t>& data) override; 164 165 /** 166 * Attempt to close a session. If the handler returns a failure 167 * in closing, the session is kept open. 168 * 169 * @param[in] session - the session for this command. 170 * @return bool - true if the session was closed. 171 */ 172 bool close(uint16_t session) override; 173 174 /** 175 * Attempt to read bytes from the blob. If there's a failure, such as 176 * an invalid offset it'll just return 0 bytes. 177 * 178 * @param[in] session - the session for this command. 179 * @param[in] offset - the offset from which to read. 180 * @param[in] requestedSize - the number of bytes to try and read. 181 * @return the bytes read. 182 */ 183 std::vector<uint8_t> read(uint16_t session, uint32_t offset, 184 uint32_t requestedSize) override; 185 186 /** 187 * Attempt to write to a blob. The manager does not track whether 188 * the session opened the file for writing. 189 * 190 * @param[in] session - the session for this command. 191 * @param[in] offset - the offset into the blob to write. 192 * @param[in] data - the bytes to write to the blob. 193 * @return bool - true if the write succeeded. 194 */ 195 bool write(uint16_t session, uint32_t offset, 196 const std::vector<uint8_t>& data) override; 197 198 /** 199 * Attempt to delete a blobId. This method will just call the 200 * handler, which will return failure if the blob doesn't support 201 * deletion. This command will also fail if there are any open 202 * sessions against the specific blob. 203 * 204 * In the case where they specify a folder, such as /blob/skm where 205 * the "real" blobIds are /blob/skm/1, or /blob/skm/2, the manager 206 * may see there are on open sessions to that specific path and will 207 * call the handler. In this case, the handler is responsible for 208 * handling any checks or logic. 209 * 210 * @param[in] path - the blobId path. 211 * @return bool - true if delete was successful. 212 */ 213 bool deleteBlob(const std::string& path) override; 214 215 /** 216 * Attempt to write Metadata to a blob. 217 * 218 * @param[in] session - the session for this command. 219 * @param[in] offset - the offset into the blob to write. 220 * @param[in] data - the bytes to write to the blob. 221 * @return bool - true if the write succeeded. 222 */ 223 bool writeMeta(uint16_t session, uint32_t offset, 224 const std::vector<uint8_t>& data) override; 225 226 /** 227 * Attempts to return a valid unique session id. 228 * 229 * @param[in,out] - pointer to the session. 230 * @return bool - true if able to allocate. 231 */ 232 bool getSession(uint16_t* session); 233 234 /** 235 * Given a file path will return first handler to answer that it owns 236 * it. 237 * 238 * @param[in] path - the file path. 239 * @return pointer to the handler or nullptr if not found. 240 */ 241 GenericBlobInterface* getHandler(const std::string& path); 242 243 /** 244 * Given a session id, update session time and return a handle to take 245 * action 246 * 247 * @param[in] session - session ID 248 * @param[in] requiredFlags - only return handle if the flags for this 249 * session contain these flags; defaults to any flag 250 * @return session handler, nullptr if cannot get handler 251 */ 252 GenericBlobInterface* getActionHandle( 253 uint16_t session, 254 uint16_t requiredFlags = std::numeric_limits<uint16_t>::max()) 255 { 256 if (auto item = sessions.find(session); 257 item != sessions.end() && (item->second.flags & requiredFlags)) 258 { 259 item->second.lastActionTime = std::chrono::steady_clock::now(); 260 return item->second.handler; 261 } 262 return nullptr; 263 } 264 265 /** 266 * Given a session id will return associated path. 267 * 268 * @param[in] session - the session. 269 * @return the path or "" on failure. 270 */ 271 std::string getPath(uint16_t session) const; 272 273 private: 274 void incrementOpen(const std::string& path); 275 void decrementOpen(const std::string& path); 276 int getOpen(const std::string& path) const; 277 278 /* The next session ID to use */ 279 uint16_t next; 280 /* Temporary list of blobIds used for enumeration. */ 281 std::vector<std::string> ids; 282 /* List of Blob handler. */ 283 std::vector<std::unique_ptr<GenericBlobInterface>> handlers; 284 /* Mapping of session ids to blob handlers and the path used with open. 285 */ 286 std::unordered_map<uint16_t, SessionInfo> sessions; 287 /* Mapping of open blobIds */ 288 std::unordered_map<std::string, int> openFiles; 289 }; 290 291 /** 292 * @brief Gets a handle to the BlobManager. 293 * 294 * @return a pointer to the BlobManager instance. 295 */ 296 ManagerInterface* getBlobManager(); 297 298 } // namespace blobs 299