1 #include "example/example.hpp"
2 
3 #include <algorithm>
4 #include <blobs-ipmid/manager.hpp>
5 #include <cstring>
6 #include <memory>
7 #include <phosphor-logging/log.hpp>
8 #include <string>
9 #include <vector>
10 
11 namespace blobs
12 {
13 
14 using namespace phosphor::logging;
15 
16 constexpr char ExampleBlobHandler::supportedPath[];
17 
18 ExampleBlob* ExampleBlobHandler::getSession(uint16_t id)
19 {
20     auto search = sessions.find(id);
21     if (search == sessions.end())
22     {
23         return nullptr;
24     }
25     /* Not thread-safe, however, the blob handler deliberately assumes serial
26      * execution. */
27     return &search->second;
28 }
29 
30 bool ExampleBlobHandler::canHandleBlob(const std::string& path)
31 {
32     return (path == supportedPath);
33 }
34 
35 std::vector<std::string> ExampleBlobHandler::getBlobIds()
36 {
37     return {supportedPath};
38 }
39 
40 bool ExampleBlobHandler::deleteBlob(const std::string& path)
41 {
42     return false;
43 }
44 
45 bool ExampleBlobHandler::stat(const std::string& path, struct BlobMeta* meta)
46 {
47     return false;
48 }
49 
50 bool ExampleBlobHandler::open(uint16_t session, uint16_t flags,
51                               const std::string& path)
52 {
53     if (!canHandleBlob(path))
54     {
55         return false;
56     }
57 
58     auto findSess = sessions.find(session);
59     if (findSess != sessions.end())
60     {
61         /* This session is already active. */
62         return false;
63     }
64     sessions[session] = ExampleBlob(session, flags);
65     return true;
66 }
67 
68 std::vector<uint8_t> ExampleBlobHandler::read(uint16_t session, uint32_t offset,
69                                               uint32_t requestedSize)
70 {
71     ExampleBlob* sess = getSession(session);
72     if (!sess)
73     {
74         return std::vector<uint8_t>();
75     }
76 
77     /* Is the offset beyond the array? */
78     if (offset >= sizeof(sess->buffer))
79     {
80         return std::vector<uint8_t>();
81     }
82 
83     /* Determine how many bytes we can read from the offset.
84      * In this case, if they read beyond "size" we allow it.
85      */
86     uint32_t remain = sizeof(sess->buffer) - offset;
87     uint32_t numBytes = std::min(remain, requestedSize);
88     /* Copy the bytes! */
89     std::vector<uint8_t> result(numBytes);
90     std::memcpy(result.data(), &sess->buffer[offset], numBytes);
91     return result;
92 }
93 
94 bool ExampleBlobHandler::write(uint16_t session, uint32_t offset,
95                                const std::vector<uint8_t>& data)
96 {
97     ExampleBlob* sess = getSession(session);
98     if (!sess)
99     {
100         return false;
101     }
102     /* Is the offset beyond the array? */
103     if (offset >= sizeof(sess->buffer))
104     {
105         return false;
106     }
107     /* Determine whether all their bytes will fit. */
108     uint32_t remain = sizeof(sess->buffer) - offset;
109     if (data.size() > remain)
110     {
111         return false;
112     }
113     sess->length =
114         std::max(offset + data.size(),
115                  static_cast<std::vector<uint8_t>::size_type>(sess->length));
116     std::memcpy(&sess->buffer[offset], data.data(), data.size());
117     return true;
118 }
119 
120 bool ExampleBlobHandler::commit(uint16_t session,
121                                 const std::vector<uint8_t>& data)
122 {
123     ExampleBlob* sess = getSession(session);
124     if (!sess)
125     {
126         return false;
127     }
128 
129     /* Do something with the staged data!. */
130 
131     return false;
132 }
133 
134 bool ExampleBlobHandler::close(uint16_t session)
135 {
136     ExampleBlob* sess = getSession(session);
137     if (!sess)
138     {
139         return false;
140     }
141 
142     sessions.erase(session);
143     return true;
144 }
145 
146 bool ExampleBlobHandler::stat(uint16_t session, struct BlobMeta* meta)
147 {
148     ExampleBlob* sess = getSession(session);
149     if (!sess)
150     {
151         return false;
152     }
153     if (!meta)
154     {
155         return false;
156     }
157     meta->size = sess->length;
158     meta->blobState = sess->state;
159     return true;
160 }
161 
162 bool ExampleBlobHandler::expire(uint16_t session)
163 {
164     ExampleBlob* sess = getSession(session);
165     if (!sess)
166     {
167         return false;
168     }
169     /* TODO: implement session expiration behavior. */
170     return false;
171 }
172 
173 void setupExampleHandler() __attribute__((constructor));
174 
175 void setupExampleHandler()
176 {
177     BlobManager* manager = getBlobManager();
178     if (!manager->registerHandler(std::make_unique<ExampleBlobHandler>()))
179     {
180         log<level::ERR>("Failed to register Example Handler");
181     }
182 }
183 
184 } // namespace blobs
185