xref: /openbmc/phosphor-ipmi-blobs/manager.hpp (revision 7fc52c8fe3bc7cc9b57a007ce1b7c38e60f9602f)
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