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::writeMeta(uint16_t session, uint32_t offset, 121 const std::vector<uint8_t>& data) 122 { 123 /* Not supported. */ 124 return false; 125 } 126 127 bool ExampleBlobHandler::commit(uint16_t session, 128 const std::vector<uint8_t>& data) 129 { 130 ExampleBlob* sess = getSession(session); 131 if (!sess) 132 { 133 return false; 134 } 135 136 /* Do something with the staged data!. */ 137 138 return false; 139 } 140 141 bool ExampleBlobHandler::close(uint16_t session) 142 { 143 ExampleBlob* sess = getSession(session); 144 if (!sess) 145 { 146 return false; 147 } 148 149 sessions.erase(session); 150 return true; 151 } 152 153 bool ExampleBlobHandler::stat(uint16_t session, struct BlobMeta* meta) 154 { 155 ExampleBlob* sess = getSession(session); 156 if (!sess) 157 { 158 return false; 159 } 160 if (!meta) 161 { 162 return false; 163 } 164 meta->size = sess->length; 165 meta->blobState = sess->state; 166 return true; 167 } 168 169 bool ExampleBlobHandler::expire(uint16_t session) 170 { 171 ExampleBlob* sess = getSession(session); 172 if (!sess) 173 { 174 return false; 175 } 176 /* TODO: implement session expiration behavior. */ 177 return false; 178 } 179 180 void setupExampleHandler() __attribute__((constructor)); 181 182 void setupExampleHandler() 183 { 184 // You don't need to do anything in the constructor. 185 } 186 187 } // namespace blobs 188 189 /** 190 * This method is required by the blob manager. 191 * 192 * It is called to grab a handler for registering the blob handler instance. 193 */ 194 std::unique_ptr<blobs::GenericBlobInterface> createHandler() 195 { 196 return std::make_unique<blobs::ExampleBlobHandler>(); 197 } 198