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