Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
file_server.hpp
00001 /* 00002 * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_PROTOCOL_FILE_SERVER_HPP_INCLUDED 00006 #define UAVCAN_PROTOCOL_FILE_SERVER_HPP_INCLUDED 00007 00008 #include <uavcan/build_config.hpp> 00009 #include <uavcan/debug.hpp> 00010 #include <uavcan/node/service_server.hpp> 00011 #include <uavcan/util/method_binder.hpp> 00012 // UAVCAN types 00013 #include <uavcan/protocol/file/GetInfo.hpp> 00014 #include <uavcan/protocol/file/GetDirectoryEntryInfo.hpp> 00015 #include <uavcan/protocol/file/Read.hpp> 00016 #include <uavcan/protocol/file/Write.hpp> 00017 #include <uavcan/protocol/file/Delete.hpp> 00018 00019 namespace uavcan 00020 { 00021 /** 00022 * The file server backend should implement this interface. 00023 * Note that error codes returned by these methods are defined in uavcan.protocol.file.Error; these are 00024 * not the same as libuavcan-internal error codes defined in uavcan.error.hpp. 00025 */ 00026 class UAVCAN_EXPORT IFileServerBackend 00027 { 00028 public: 00029 typedef protocol::file::Path::FieldTypes::path Path; 00030 typedef protocol::file::EntryType EntryType; 00031 typedef protocol::file::Error Error; 00032 00033 /** 00034 * All read operations must return this number of bytes, unless end of file is reached. 00035 */ 00036 enum { ReadSize = protocol::file::Read::Response::FieldTypes::data::MaxSize }; 00037 00038 /** 00039 * Shortcut for uavcan.protocol.file.Path.SEPARATOR. 00040 */ 00041 static char getPathSeparator() { return static_cast<char>(protocol::file::Path::SEPARATOR); } 00042 00043 /** 00044 * Backend for uavcan.protocol.file.GetInfo. 00045 * Refer to uavcan.protocol.file.EntryType for the list of available bit flags. 00046 * Implementation of this method is required. 00047 * On success the method must return zero. 00048 */ 00049 virtual int16_t getInfo(const Path& path, uint64_t& out_size, EntryType& out_type) = 0; 00050 00051 /** 00052 * Backend for uavcan.protocol.file.Read. 00053 * Implementation of this method is required. 00054 * @ref inout_size is set to @ref ReadSize; read operation is required to return exactly this amount, except 00055 * if the end of file is reached. 00056 * On success the method must return zero. 00057 */ 00058 virtual int16_t read(const Path& path, const uint64_t offset, uint8_t* out_buffer, uint16_t& inout_size) = 0; 00059 00060 // Methods below are optional. 00061 00062 /** 00063 * Backend for uavcan.protocol.file.Write. 00064 * Implementation of this method is NOT required; by default it returns uavcan.protocol.file.Error.NOT_IMPLEMENTED. 00065 * On success the method must return zero. 00066 */ 00067 virtual int16_t write(const Path& path, const uint64_t offset, const uint8_t* buffer, const uint16_t size) 00068 { 00069 (void)path; 00070 (void)offset; 00071 (void)buffer; 00072 (void)size; 00073 return Error::NOT_IMPLEMENTED; 00074 } 00075 00076 /** 00077 * Backend for uavcan.protocol.file.Delete. ('delete' is a C++ keyword, so 'remove' is used instead) 00078 * Implementation of this method is NOT required; by default it returns uavcan.protocol.file.Error.NOT_IMPLEMENTED. 00079 * On success the method must return zero. 00080 */ 00081 virtual int16_t remove(const Path& path) 00082 { 00083 (void)path; 00084 return Error::NOT_IMPLEMENTED; 00085 } 00086 00087 /** 00088 * Backend for uavcan.protocol.file.GetDirectoryEntryInfo. 00089 * Refer to uavcan.protocol.file.EntryType for the list of available bit flags. 00090 * Implementation of this method is NOT required; by default it returns uavcan.protocol.file.Error.NOT_IMPLEMENTED. 00091 * On success the method must return zero. 00092 */ 00093 virtual int16_t getDirectoryEntryInfo(const Path& directory_path, const uint32_t entry_index, 00094 EntryType& out_type, Path& out_entry_full_path) 00095 { 00096 (void)directory_path; 00097 (void)entry_index; 00098 (void)out_type; 00099 (void)out_entry_full_path; 00100 return Error::NOT_IMPLEMENTED; 00101 } 00102 00103 virtual ~IFileServerBackend() { } 00104 }; 00105 00106 /** 00107 * Basic file server implements only the following services: 00108 * uavcan.protocol.file.GetInfo 00109 * uavcan.protocol.file.Read 00110 * Also see @ref IFileServerBackend. 00111 */ 00112 class BasicFileServer 00113 { 00114 typedef MethodBinder<BasicFileServer*, 00115 void (BasicFileServer::*)(const protocol::file::GetInfo::Request&, protocol::file::GetInfo::Response&)> 00116 GetInfoCallback; 00117 00118 typedef MethodBinder<BasicFileServer*, 00119 void (BasicFileServer::*)(const protocol::file::Read::Request&, protocol::file::Read::Response&)> 00120 ReadCallback; 00121 00122 ServiceServer<protocol::file::GetInfo, GetInfoCallback> get_info_srv_; 00123 ServiceServer<protocol::file::Read, ReadCallback> read_srv_; 00124 00125 void handleGetInfo(const protocol::file::GetInfo::Request& req, protocol::file::GetInfo::Response& resp) 00126 { 00127 resp.error.value = backend_.getInfo(req.path.path, resp.size, resp.entry_type); 00128 } 00129 00130 void handleRead(const protocol::file::Read::Request& req, protocol::file::Read::Response& resp) 00131 { 00132 uint16_t inout_size = resp.data.capacity(); 00133 00134 resp.data.resize(inout_size); 00135 00136 resp.error.value = backend_.read(req.path.path, req.offset, resp.data.begin(), inout_size); 00137 00138 if (resp.error.value != protocol::file::Error::OK) 00139 { 00140 inout_size = 0; 00141 } 00142 00143 if (inout_size > resp.data.capacity()) 00144 { 00145 UAVCAN_ASSERT(0); 00146 resp.error.value = protocol::file::Error::UNKNOWN_ERROR; 00147 } 00148 else 00149 { 00150 resp.data.resize(inout_size); 00151 } 00152 } 00153 00154 protected: 00155 IFileServerBackend& backend_; ///< Derived types can use it 00156 00157 public: 00158 BasicFileServer(INode& node, IFileServerBackend& backend) 00159 : get_info_srv_(node) 00160 , read_srv_(node) 00161 , backend_(backend) 00162 { } 00163 00164 int start() 00165 { 00166 int res = get_info_srv_.start(GetInfoCallback(this, &BasicFileServer::handleGetInfo)); 00167 if (res < 0) 00168 { 00169 return res; 00170 } 00171 00172 res = read_srv_.start(ReadCallback(this, &BasicFileServer::handleRead)); 00173 if (res < 0) 00174 { 00175 return res; 00176 } 00177 00178 return 0; 00179 } 00180 }; 00181 00182 /** 00183 * Full file server implements all file services: 00184 * uavcan.protocol.file.GetInfo 00185 * uavcan.protocol.file.Read 00186 * uavcan.protocol.file.Write 00187 * uavcan.protocol.file.Delete 00188 * uavcan.protocol.file.GetDirectoryEntryInfo 00189 * Also see @ref IFileServerBackend. 00190 */ 00191 class FileServer : protected BasicFileServer 00192 { 00193 typedef MethodBinder<FileServer*, 00194 void (FileServer::*)(const protocol::file::Write::Request&, protocol::file::Write::Response&)> 00195 WriteCallback; 00196 00197 typedef MethodBinder<FileServer*, 00198 void (FileServer::*)(const protocol::file::Delete::Request&, protocol::file::Delete::Response&)> 00199 DeleteCallback; 00200 00201 typedef MethodBinder<FileServer*, 00202 void (FileServer::*)(const protocol::file::GetDirectoryEntryInfo::Request&, 00203 protocol::file::GetDirectoryEntryInfo::Response&)> 00204 GetDirectoryEntryInfoCallback; 00205 00206 ServiceServer<protocol::file::Write, WriteCallback> write_srv_; 00207 ServiceServer<protocol::file::Delete, DeleteCallback> delete_srv_; 00208 ServiceServer<protocol::file::GetDirectoryEntryInfo, GetDirectoryEntryInfoCallback> get_directory_entry_info_srv_; 00209 00210 void handleWrite(const protocol::file::Write::Request& req, protocol::file::Write::Response& resp) 00211 { 00212 resp.error.value = backend_.write(req.path.path, req.offset, req.data.begin(), req.data.size()); 00213 } 00214 00215 void handleDelete(const protocol::file::Delete::Request& req, protocol::file::Delete::Response& resp) 00216 { 00217 resp.error.value = backend_.remove(req.path.path); 00218 } 00219 00220 void handleGetDirectoryEntryInfo(const protocol::file::GetDirectoryEntryInfo::Request& req, 00221 protocol::file::GetDirectoryEntryInfo::Response& resp) 00222 { 00223 resp.error.value = backend_.getDirectoryEntryInfo(req.directory_path.path, req.entry_index, 00224 resp.entry_type, resp.entry_full_path.path); 00225 } 00226 00227 public: 00228 FileServer(INode& node, IFileServerBackend& backend) 00229 : BasicFileServer(node, backend) 00230 , write_srv_(node) 00231 , delete_srv_(node) 00232 , get_directory_entry_info_srv_(node) 00233 { } 00234 00235 int start() 00236 { 00237 int res = BasicFileServer::start(); 00238 if (res < 0) 00239 { 00240 return res; 00241 } 00242 00243 res = write_srv_.start(WriteCallback(this, &FileServer::handleWrite)); 00244 if (res < 0) 00245 { 00246 return res; 00247 } 00248 00249 res = delete_srv_.start(DeleteCallback(this, &FileServer::handleDelete)); 00250 if (res < 0) 00251 { 00252 return res; 00253 } 00254 00255 res = get_directory_entry_info_srv_.start( 00256 GetDirectoryEntryInfoCallback(this, &FileServer::handleGetDirectoryEntryInfo)); 00257 if (res < 0) 00258 { 00259 return res; 00260 } 00261 00262 return 0; 00263 } 00264 }; 00265 00266 } 00267 00268 #endif // Include guard
Generated on Tue Jul 12 2022 17:17:31 by
