diff --git a/CMakeLists.txt b/CMakeLists.txt index 71c776f..a30fb92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,8 @@ add_library(webfuse_static STATIC src/webfuse/filesystem/empty_filesystem.cpp src/webfuse/ws/config.cpp src/webfuse/ws/server.cpp - src/webfuse/ws/message.cpp + src/webfuse/ws/messagewriter.cpp + src/webfuse/ws/messagereader.cpp ) target_include_directories(webfuse_static PUBLIC src) diff --git a/script/provider.py b/script/provider.py index dc76f11..564bcd0 100755 --- a/script/provider.py +++ b/script/provider.py @@ -98,11 +98,24 @@ class MessageWriter: self.buffer.append(value) def write_u32(self, value): - a = (value >> 24) & 0xff - b = (value >> 16) & 0xff - c = (value >> 8) & 0xff - d = value & 0xff - self.buffer.extend([a, b, c, d]) + self.buffer.extend([ + (value >> 24) & 0xff, + (value >> 16) & 0xff, + (value >> 8) & 0xff, + value & 0xff + ]) + + def write_u64(self, value): + self.buffer.extend([ + (value >> 56) & 0xff, + (value >> 48) & 0xff, + (value >> 40) & 0xff, + (value >> 32) & 0xff, + (value >> 24) & 0xff, + (value >> 16) & 0xff, + (value >> 8) & 0xff, + value & 0xff + ]) def write_i32(self, value): self.write_u32(value & 0xffffffff) @@ -113,7 +126,23 @@ class MessageWriter: value = ERRNO[value] self.write_i32(value) + def write_str(self, value): + data = value.encode('utf-8') + self.write_bytes(data) + + def write_bytes(self, value): + size = len(value) + self.write_u32(size) + self.buffer.extend(value) + + def write_strings(self, values): + count = len(values) + self.write_u32(count) + for value in values: + self.write_str(value) + def get_bytes(self): + print(self.buffer) return bytearray(self.buffer) @@ -122,7 +151,9 @@ class FilesystemProvider: self.root = os.path.abspath(path) self.url = url self.commands = { - 0x01: FilesystemProvider.access + 0x01: FilesystemProvider.access, + 0x02: FilesystemProvider.getattr, + 0x13: FilesystemProvider.readdir } async def run(self): @@ -132,6 +163,7 @@ class FilesystemProvider: reader = MessageReader(request) message_id = reader.read_u32() message_type = reader.read_u8() + print("received message: id=%d, type=%d" % (message_id, message_type)) writer = MessageWriter(message_id, RESPONSE + message_type) if message_type in self.commands: method = self.commands[message_type] @@ -152,6 +184,43 @@ class FilesystemProvider: result = -ex.errno writer.write_result(result) + def getattr(self, reader, writer): + path = reader.read_path(self.root) + try: + attr = os.lstat(path) + except OSError as ex: + writer.write_result(-ex.errno) + return + writer.write_result(0) + writer.write_u64(attr.st_ino) + writer.write_u64(attr.st_nlink) + writer.write_u32(attr.st_mode) + writer.write_i32(attr.st_uid) + writer.write_i32(attr.st_gid) + writer.write_u64(attr.st_dev) + writer.write_u64(attr.st_size) + writer.write_u64(attr.st_blocks) + writer.write_u64(int(attr.st_atime)) + writer.write_u32(attr.st_atime_ns) + writer.write_u64(int(attr.st_mtime)) + writer.write_u32(attr.st_mtime_ns) + writer.write_u64(int(attr.st_ctime)) + writer.write_u32(attr.st_ctime_ns) + + def readdir(self, reader, writer): + path = reader.read_path(self.root) + names = [] + try: + with os.scandir(path) as it: + for entry in it: + names.append(entry.name) + except OSError as ex: + writer.write_result(-ex.errno) + return + writer.write_result(0) + writer.write_strings(names) + + if __name__ == '__main__': provider = FilesystemProvider('.', 'ws://localhost:8081') asyncio.run(provider.run()) diff --git a/src/webfuse/filesystem.cpp b/src/webfuse/filesystem.cpp index cf7dd60..d895aac 100644 --- a/src/webfuse/filesystem.cpp +++ b/src/webfuse/filesystem.cpp @@ -1,4 +1,5 @@ #include "webfuse/filesystem.hpp" +#include namespace webfuse { @@ -14,15 +15,15 @@ filesystem::~filesystem() } -status filesystem::access(std::string const & path, access_mode mode) +int filesystem::access(std::string const & path, int mode) { try { - message req(message_type::access_req); - req.add_str(path); - req.add_i8(mode); - proxy.perform(std::move(req)); - return status::bad_enoent; + messagewriter req(message_type::access_req); + req.write_str(path); + req.write_access_mode(mode); + auto reader = proxy.perform(std::move(req)); + return reader.read_result(); } catch(...) { @@ -30,27 +31,34 @@ status filesystem::access(std::string const & path, access_mode mode) } } -status filesystem::getattr(std::string const & path, file_attributes & attr) +int filesystem::getattr(std::string const & path, struct stat * attr) { try { - message req(message_type::getattr_req); - proxy.perform(std::move(req)); - return status::bad_enoent; + messagewriter req(message_type::getattr_req); + req.write_str(path); + auto reader = proxy.perform(std::move(req)); + int const result = reader.read_result(); + if (0 == result) + { + reader.read_attr(attr); + } + return result; } catch(...) { + puts("getattr: failed"); return fallback.getattr(path, attr); } } -status filesystem::readlink(std::string const & path, std::string & out) +int filesystem::readlink(std::string const & path, std::string & out) { try { - message req(message_type::readlink_req); + messagewriter req(message_type::readlink_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -58,13 +66,13 @@ status filesystem::readlink(std::string const & path, std::string & out) } } -status filesystem::symlink(std::string const & target, std::string const & linkpath) +int filesystem::symlink(std::string const & target, std::string const & linkpath) { try { - message req(message_type::symlink_req); + messagewriter req(message_type::symlink_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -72,13 +80,13 @@ status filesystem::symlink(std::string const & target, std::string const & linkp } } -status filesystem::link(std::string const & old_path, std::string const & new_path) +int filesystem::link(std::string const & old_path, std::string const & new_path) { try { - message req(message_type::link_req); + messagewriter req(message_type::link_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -86,27 +94,27 @@ status filesystem::link(std::string const & old_path, std::string const & new_pa } } -status filesystem::rename(std::string const & old_path, std::string const & new_path) +int filesystem::rename(std::string const & old_path, std::string const & new_path, int flags) { try { - message req(message_type::rename_req); + messagewriter req(message_type::rename_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { - return fallback.rename(old_path, new_path); + return fallback.rename(old_path, new_path, flags); } } -status filesystem::chmod(std::string const & path, filemode mode) +int filesystem::chmod(std::string const & path, mode_t mode) { try { - message req(message_type::chmod_req); + messagewriter req(message_type::chmod_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -114,13 +122,13 @@ status filesystem::chmod(std::string const & path, filemode mode) } } -status filesystem::chown(std::string const & path, user_id uid, group_id gid) +int filesystem::chown(std::string const & path, uid_t uid, gid_t gid) { try { - message req(message_type::chown_req); + messagewriter req(message_type::chown_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -128,27 +136,27 @@ status filesystem::chown(std::string const & path, user_id uid, group_id gid) } } -status filesystem::truncate(std::string const & path, uint64_t offset, filehandle handle) +int filesystem::truncate(std::string const & path, uint64_t size, uint64_t handle) { try { - message req(message_type::truncate_req); + messagewriter req(message_type::truncate_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { - return fallback.truncate(path, offset, handle); + return fallback.truncate(path, size, handle); } } -status filesystem::fsync(std::string const & path, bool is_datasync, filehandle handle) +int filesystem::fsync(std::string const & path, bool is_datasync, uint64_t handle) { try { - message req(message_type::fsync_req); + messagewriter req(message_type::fsync_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -156,13 +164,13 @@ status filesystem::fsync(std::string const & path, bool is_datasync, filehandle } } -status filesystem::open(std::string const & path, openflags flags, filehandle & handle) +int filesystem::open(std::string const & path, int flags, uint64_t & handle) { try { - message req(message_type::open_req); + messagewriter req(message_type::open_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -170,13 +178,13 @@ status filesystem::open(std::string const & path, openflags flags, filehandle & } } -status filesystem::mknod(std::string const & path, filemode mode, uint64_t rdev) +int filesystem::mknod(std::string const & path, mode_t mode, dev_t rdev) { try { - message req(message_type::mknod_req); + messagewriter req(message_type::mknod_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -184,13 +192,13 @@ status filesystem::mknod(std::string const & path, filemode mode, uint64_t rdev) } } -status filesystem::create(std::string const & path, filemode mode, filehandle & handle) +int filesystem::create(std::string const & path, mode_t mode, uint64_t & handle) { try { - message req(message_type::create_req); + messagewriter req(message_type::create_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -198,13 +206,13 @@ status filesystem::create(std::string const & path, filemode mode, filehandle & } } -status filesystem::release(std::string const & path, filehandle handle) +int filesystem::release(std::string const & path, uint64_t handle) { try { - message req(message_type::release_req); + messagewriter req(message_type::release_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -212,13 +220,13 @@ status filesystem::release(std::string const & path, filehandle handle) } } -status filesystem::unlink(std::string const & path) +int filesystem::unlink(std::string const & path) { try { - message req(message_type::unlink_req); + messagewriter req(message_type::unlink_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -226,13 +234,13 @@ status filesystem::unlink(std::string const & path) } } -status filesystem::read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, filehandle handle) +int filesystem::read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) { try { - message req(message_type::read_req); + messagewriter req(message_type::read_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -240,13 +248,13 @@ status filesystem::read(std::string const & path, char * buffer, size_t buffer_s } } -status filesystem::write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, filehandle handle) +int filesystem::write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) { try { - message req(message_type::write_req); + messagewriter req(message_type::write_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -254,13 +262,13 @@ status filesystem::write(std::string const & path, char const * buffer, size_t b } } -status filesystem::mkdir(std::string const & path, filemode mode) +int filesystem::mkdir(std::string const & path, mode_t mode) { try { - message req(message_type::mkdir_req); + messagewriter req(message_type::mkdir_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -268,13 +276,19 @@ status filesystem::mkdir(std::string const & path, filemode mode) } } -status filesystem::readdir(std::string const & path, std::vector & entries, filehandle handle) +int filesystem::readdir(std::string const & path, std::vector & entries, uint64_t handle) { try { - message req(message_type::readdir_req); - proxy.perform(std::move(req)); - return status::bad_enoent; + messagewriter req(message_type::readdir_req); + req.write_str(path); + auto resp = proxy.perform(std::move(req)); + int result = resp.read_result(); + if (0 == result) + { + resp.read_strings(entries); + } + return result; } catch(...) { @@ -282,13 +296,13 @@ status filesystem::readdir(std::string const & path, std::vector & } } -status filesystem::rmdir(std::string const & path) +int filesystem::rmdir(std::string const & path) { try { - message req(message_type::rmdir_req); + messagewriter req(message_type::rmdir_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { @@ -296,13 +310,13 @@ status filesystem::rmdir(std::string const & path) } } -status filesystem::statfs(std::string const & path, filesystem_statistics & statistics) +int filesystem::statfs(std::string const & path, struct statvfs * statistics) { try { - message req(message_type::statfs_req); + messagewriter req(message_type::statfs_req); proxy.perform(std::move(req)); - return status::bad_enoent; + return -ENOENT; } catch(...) { diff --git a/src/webfuse/filesystem.hpp b/src/webfuse/filesystem.hpp index 6f86944..8b3c44c 100644 --- a/src/webfuse/filesystem.hpp +++ b/src/webfuse/filesystem.hpp @@ -18,33 +18,33 @@ public: explicit filesystem(ws_server& server); ~filesystem() override; - status access(std::string const & path, access_mode mode) override; - status getattr(std::string const & path, file_attributes & attr) override; + int access(std::string const & path, int mode) override; + int getattr(std::string const & path, struct stat * attr) override; - status readlink(std::string const & path, std::string & out) override; - status symlink(std::string const & target, std::string const & linkpath) override; - status link(std::string const & old_path, std::string const & new_path) override; + int readlink(std::string const & path, std::string & out) override; + int symlink(std::string const & target, std::string const & linkpath) override; + int link(std::string const & old_path, std::string const & new_path) override; - status rename(std::string const & old_path, std::string const & new_path) override; - status chmod(std::string const & path, filemode mode) override; - status chown(std::string const & path, user_id uid, group_id gid) override; - status truncate(std::string const & path, uint64_t offset, filehandle handle) override; - status fsync(std::string const & path, bool is_datasync, filehandle handle) override; + int rename(std::string const & old_path, std::string const & new_path, int flags) override; + int chmod(std::string const & path, mode_t mode) override; + int chown(std::string const & path, uid_t uid, gid_t gid) override; + int truncate(std::string const & path, uint64_t size, uint64_t handle) override; + int fsync(std::string const & path, bool is_datasync, uint64_t handle) override; - status open(std::string const & path, openflags flags, filehandle & handle) override; - status mknod(std::string const & path, filemode mode, uint64_t rdev) override; - status create(std::string const & path, filemode mode, filehandle & handle) override; - status release(std::string const & path, filehandle handle) override; - status unlink(std::string const & path) override; + int open(std::string const & path, int flags, uint64_t & handle) override; + int mknod(std::string const & path, mode_t mode, dev_t rdev) override; + int create(std::string const & path, mode_t mode, uint64_t & handle) override; + int release(std::string const & path, uint64_t handle) override; + int unlink(std::string const & path) override; - status read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, filehandle handle) override; - status write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, filehandle handle) override; + int read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) override; + int write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) override; - status mkdir(std::string const & path, filemode mode) override; - status readdir(std::string const & path, std::vector & entries, filehandle handle) override; - status rmdir(std::string const & path) override; + int mkdir(std::string const & path, mode_t mode) override; + int readdir(std::string const & path, std::vector & entries, uint64_t handle) override; + int rmdir(std::string const & path) override; - status statfs(std::string const & path, filesystem_statistics & statistics) override; + int statfs(std::string const & path, struct statvfs * statistics) override; private: diff --git a/src/webfuse/filesystem/empty_filesystem.cpp b/src/webfuse/filesystem/empty_filesystem.cpp index 9993cda..6552d2e 100644 --- a/src/webfuse/filesystem/empty_filesystem.cpp +++ b/src/webfuse/filesystem/empty_filesystem.cpp @@ -1,134 +1,135 @@ #include "webfuse/filesystem/empty_filesystem.hpp" +#include namespace webfuse { -status empty_filesystem::access(std::string const & path, access_mode mode) +int empty_filesystem::access(std::string const & path, int mode) { if (path == "/") { - return status::good; + return 0; } else { - return status::bad_enoent; + return -ENOENT; } } -status empty_filesystem::getattr(std::string const & path, file_attributes & attr) +int empty_filesystem::getattr(std::string const & path, struct stat * attr) { if (path == "/") { - attr.inode = 1; - attr.nlink = 1; - attr.mode = filemode(filemode::dir | 0x444); - return status::good; + attr->st_ino = 1; + attr->st_nlink = 1; + attr->st_mode = S_IFDIR | 0x444; + return 0; } else { - return status::bad_enoent; + return -ENOENT; } } -status empty_filesystem::readlink(std::string const & path, std::string & out) +int empty_filesystem::readlink(std::string const & path, std::string & out) { - return status::bad_enoent; + return -ENOENT; } -status empty_filesystem::symlink(std::string const & target, std::string const & linkpath) +int empty_filesystem::symlink(std::string const & target, std::string const & linkpath) { - return status::bad_enoent; + return -ENOENT; } -status empty_filesystem::link(std::string const & old_path, std::string const & new_path) +int empty_filesystem::link(std::string const & old_path, std::string const & new_path) { - return status::bad_enoent; + return -ENOENT; } -status empty_filesystem::rename(std::string const & old_path, std::string const & new_path) +int empty_filesystem::rename(std::string const & old_path, std::string const & new_path, int flags) { - return status::bad_enoent; + return -ENOENT; } -status empty_filesystem::chmod(std::string const & path, filemode mode) +int empty_filesystem::chmod(std::string const & path, mode_t mode) { - return status::bad_eperm; + return -EPERM; } -status empty_filesystem::chown(std::string const & path, user_id uid, group_id gid) +int empty_filesystem::chown(std::string const & path, uid_t uid, gid_t gid) { - return status::bad_eperm; + return -EPERM; } -status empty_filesystem::truncate(std::string const & path, uint64_t offset, filehandle handle) +int empty_filesystem::truncate(std::string const & path, uint64_t size, uint64_t handle) { - return status::bad_eperm; + return -EPERM; } -status empty_filesystem::fsync(std::string const & path, bool is_datasync, filehandle handle) +int empty_filesystem::fsync(std::string const & path, bool is_datasync, uint64_t handle) { - return status::good; + return 0; } -status empty_filesystem::open(std::string const & path, openflags flags, filehandle & handle) +int empty_filesystem::open(std::string const & path, int flags, uint64_t & handle) { - return status::bad_enoent; + return -ENOENT; } -status empty_filesystem::mknod(std::string const & path, filemode mode, uint64_t rdev) +int empty_filesystem::mknod(std::string const & path, mode_t mode, dev_t rdev) { - return status::bad_eperm; + return -EPERM; } -status empty_filesystem::create(std::string const & path, filemode mode, filehandle & handle) +int empty_filesystem::create(std::string const & path, mode_t mode, uint64_t & handle) { - return status::bad_eperm; + return -EPERM; } -status empty_filesystem::release(std::string const & path, filehandle handle) +int empty_filesystem::release(std::string const & path, uint64_t handle) { - return status::good; + return 0; } -status empty_filesystem::unlink(std::string const & path) +int empty_filesystem::unlink(std::string const & path) { - return status::bad_eperm; + return -EPERM; } -status empty_filesystem::read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, filehandle handle) +int empty_filesystem::read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) { - return status::bad_ebadf; + return -EBADF; } -status empty_filesystem::write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, filehandle handle) +int empty_filesystem::write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) { - return status::bad_ebadf; + return -EBADF; } -status empty_filesystem::mkdir(std::string const & path, filemode mode) +int empty_filesystem::mkdir(std::string const & path, mode_t mode) { - return status::bad_eperm; + return -EPERM; } -status empty_filesystem::readdir(std::string const & path, std::vector & entries, filehandle handle) +int empty_filesystem::readdir(std::string const & path, std::vector & entries, uint64_t handle) { if (path == "/") { - return status::good; + return 0; } else { - return status::bad_enoent; + return -ENOENT; } } -status empty_filesystem::rmdir(std::string const & path) +int empty_filesystem::rmdir(std::string const & path) { - return status::bad_eperm; + return -EPERM; } -status empty_filesystem::statfs(std::string const & path, filesystem_statistics & statistics) +int empty_filesystem::statfs(std::string const & path, struct statvfs * statistics) { - return status::bad_enosys; + return -ENOSYS; } diff --git a/src/webfuse/filesystem/empty_filesystem.hpp b/src/webfuse/filesystem/empty_filesystem.hpp index b020f03..b26477f 100644 --- a/src/webfuse/filesystem/empty_filesystem.hpp +++ b/src/webfuse/filesystem/empty_filesystem.hpp @@ -11,33 +11,33 @@ class empty_filesystem: public filesystem_i public: ~empty_filesystem() override = default; - status access(std::string const & path, access_mode mode) override; - status getattr(std::string const & path, file_attributes & attr) override; + int access(std::string const & path, int mode) override; + int getattr(std::string const & path, struct stat * attr) override; - status readlink(std::string const & path, std::string & out) override; - status symlink(std::string const & target, std::string const & linkpath) override; - status link(std::string const & old_path, std::string const & new_path) override; + int readlink(std::string const & path, std::string & out) override; + int symlink(std::string const & target, std::string const & linkpath) override; + int link(std::string const & old_path, std::string const & new_path) override; - status rename(std::string const & old_path, std::string const & new_path) override; - status chmod(std::string const & path, filemode mode) override; - status chown(std::string const & path, user_id uid, group_id gid) override; - status truncate(std::string const & path, uint64_t offset, filehandle handle) override; - status fsync(std::string const & path, bool is_datasync, filehandle handle) override; + int rename(std::string const & old_path, std::string const & new_path, int flags) override; + int chmod(std::string const & path, mode_t mode) override; + int chown(std::string const & path, uid_t uid, gid_t gid) override; + int truncate(std::string const & path, uint64_t size, uint64_t handle) override; + int fsync(std::string const & path, bool is_datasync, uint64_t handle) override; - status open(std::string const & path, openflags flags, filehandle & handle) override; - status mknod(std::string const & path, filemode mode, uint64_t rdev) override; - status create(std::string const & path, filemode mode, filehandle & handle) override; - status release(std::string const & path, filehandle handle) override; - status unlink(std::string const & path) override; + int open(std::string const & path, int flags, uint64_t & handle) override; + int mknod(std::string const & path, mode_t mode, dev_t rdev) override; + int create(std::string const & path, mode_t mode, uint64_t & handle) override; + int release(std::string const & path, uint64_t handle) override; + int unlink(std::string const & path) override; - status read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, filehandle handle) override; - status write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, filehandle handle) override; + int read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) override; + int write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) override; - status mkdir(std::string const & path, filemode mode) override; - status readdir(std::string const & path, std::vector & entries, filehandle handle) override; - status rmdir(std::string const & path) override; + int mkdir(std::string const & path, mode_t mode) override; + int readdir(std::string const & path, std::vector & entries, uint64_t handle) override; + int rmdir(std::string const & path) override; - status statfs(std::string const & path, filesystem_statistics & statistics) override; + int statfs(std::string const & path, struct statvfs * statistivs) override; }; } diff --git a/src/webfuse/filesystem/filesystem_i.hpp b/src/webfuse/filesystem/filesystem_i.hpp index 84b585e..d1de857 100644 --- a/src/webfuse/filesystem/filesystem_i.hpp +++ b/src/webfuse/filesystem/filesystem_i.hpp @@ -1,15 +1,10 @@ #ifndef WEBFUSE_FILESYSTEM_I_HPP #define WEBFUSE_FILESYSTEM_I_HPP -#include "webfuse/filesystem/filehandle.hpp" -#include "webfuse/filesystem/accessmode.hpp" -#include "webfuse/filesystem/filemode.hpp" -#include "webfuse/filesystem/fileattributes.hpp" -#include "webfuse/filesystem/openflags.hpp" -#include "webfuse/filesystem/userid.hpp" -#include "webfuse/filesystem/groupid.hpp" -#include "webfuse/filesystem/status.hpp" -#include "webfuse/filesystem/filesystem_statistics.hpp" +#include +#include +#include +#include #include #include @@ -23,33 +18,33 @@ class filesystem_i public: virtual ~filesystem_i() = default; - virtual status access(std::string const & path, access_mode mode) = 0; - virtual status getattr(std::string const & path, file_attributes & attr) = 0; + virtual int access(std::string const & path, int mode) = 0; + virtual int getattr(std::string const & path, struct stat * attr) = 0; - virtual status readlink(std::string const & path, std::string & out) = 0; - virtual status symlink(std::string const & target, std::string const & linkpath) = 0; - virtual status link(std::string const & old_path, std::string const & new_path) = 0; + virtual int readlink(std::string const & path, std::string & out) = 0; + virtual int symlink(std::string const & target, std::string const & linkpath) = 0; + virtual int link(std::string const & old_path, std::string const & new_path) = 0; - virtual status rename(std::string const & old_path, std::string const & new_path) = 0; - virtual status chmod(std::string const & path, filemode mode) = 0; - virtual status chown(std::string const & path, user_id uid, group_id gid) = 0; - virtual status truncate(std::string const & path, uint64_t offset, filehandle handle) = 0; - virtual status fsync(std::string const & path, bool is_datasync, filehandle handle) = 0; + virtual int rename(std::string const & old_path, std::string const & new_path, int flags) = 0; + virtual int chmod(std::string const & path, mode_t mode) = 0; + virtual int chown(std::string const & path, uid_t uid, gid_t gid) = 0; + virtual int truncate(std::string const & path, uint64_t size, uint64_t handle) = 0; + virtual int fsync(std::string const & path, bool is_datasync, uint64_t handle) = 0; - virtual status open(std::string const & path, openflags flags, filehandle & handle) = 0; - virtual status mknod(std::string const & path, filemode mode, uint64_t rdev) = 0; - virtual status create(std::string const & path, filemode mode, filehandle & handle) = 0; - virtual status release(std::string const & path, filehandle handle) = 0; - virtual status unlink(std::string const & path) = 0; + virtual int open(std::string const & path, int flags, uint64_t & handle) = 0; + virtual int mknod(std::string const & path, mode_t mode, dev_t rdev) = 0; + virtual int create(std::string const & path, mode_t mode, uint64_t & handle) = 0; + virtual int release(std::string const & path, uint64_t handle) = 0; + virtual int unlink(std::string const & path) = 0; - virtual status read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, filehandle handle) = 0; - virtual status write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, filehandle handle) = 0; + virtual int read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) = 0; + virtual int write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) = 0; - virtual status mkdir(std::string const & path, filemode mode) = 0; - virtual status readdir(std::string const & path, std::vector & entries, filehandle handle) = 0; - virtual status rmdir(std::string const & path) = 0; + virtual int mkdir(std::string const & path, mode_t mode) = 0; + virtual int readdir(std::string const & path, std::vector & entries, uint64_t handle) = 0; + virtual int rmdir(std::string const & path) = 0; - virtual status statfs(std::string const & path, filesystem_statistics & statistics) = 0; + virtual int statfs(std::string const & path, struct statvfs * statistics) = 0; }; } diff --git a/src/webfuse/fuse.cpp b/src/webfuse/fuse.cpp index 4ed7a49..5fd8cac 100644 --- a/src/webfuse/fuse.cpp +++ b/src/webfuse/fuse.cpp @@ -15,9 +15,9 @@ static webfuse::filesystem_i * fs_get_filesystem() return reinterpret_cast(private_data); } -static webfuse::filehandle fs_get_handle(fuse_file_info * info) +static uint64_t fs_get_handle(fuse_file_info * info) { - return (nullptr != info) ? info->fh : webfuse::invalid_handle; + return (nullptr != info) ? info->fh : ((uint64_t) -1); } static void * fs_init(fuse_conn_info * connection, fuse_config * config) @@ -33,24 +33,18 @@ static void * fs_init(fuse_conn_info * connection, fuse_config * config) } -static int fs_access(char const * path, int raw_mode) +static int fs_access(char const * path, int mode) { auto * const fs = fs_get_filesystem(); - auto const mode = webfuse::access_mode::from_int(raw_mode); - auto const result = fs->access(path, mode); - - return result.to_fusestatus(); + return fs->access(path, mode); } static int fs_getattr(char const * path, struct stat * buffer, fuse_file_info * info) { - auto * const fs = fs_get_filesystem(); - webfuse::file_attributes attributes(*buffer); - - auto const result = fs->getattr(path, attributes); - attributes.to_stat(*buffer); + (void) info; - return result.to_fusestatus(); + auto * const fs = fs_get_filesystem(); + return fs->getattr(path, buffer); } static int fs_readlink(char const * path, char * buffer, size_t buffer_size) @@ -59,63 +53,55 @@ static int fs_readlink(char const * path, char * buffer, size_t buffer_size) std::string out; auto result = fs->readlink(path, out); - if (webfuse::status::good == result) + if (0 == result) { snprintf(buffer, buffer_size, "%s", out.c_str()); result = strlen(buffer); } - return result.to_fusestatus(); + return result; } static int fs_symlink(char const * target, char const * linkpath) { auto * const fs = fs_get_filesystem(); - auto const result = fs->symlink(target, linkpath); - return result.to_fusestatus(); + return fs->symlink(target, linkpath); } static int fs_link(char const * old_path, char const * new_path) { auto * const fs = fs_get_filesystem(); - auto const result = fs->link(old_path, new_path); - return result.to_fusestatus(); + return fs->link(old_path, new_path); } static int fs_rename(char const * from, char const * to, unsigned int flags) { - // ToDo: provide flags auto * const fs = fs_get_filesystem(); - auto const result = fs->rename(from, to); - return result.to_fusestatus(); + return fs->rename(from, to, flags); } -static int fs_chmod(char const * path, mode_t raw_mode, fuse_file_info * info) +static int fs_chmod(char const * path, mode_t mode, fuse_file_info * info) { + (void) info; + auto * const fs = fs_get_filesystem(); - auto const mode = webfuse::filemode::from_mode(raw_mode); - auto const result = fs->chmod(path, mode); - return result.to_fusestatus(); + return fs->chmod(path, mode); } -static int fs_chown(char const * path, uid_t raw_uid, - gid_t raw_gid, fuse_file_info * info) +static int fs_chown(char const * path, uid_t uid, gid_t gid, fuse_file_info * info) { + (void) info; + auto * const fs = fs_get_filesystem(); - auto const uid = webfuse::user_id::from_uid(raw_uid); - auto const gid = webfuse::group_id::from_gid(raw_gid); - auto const result = fs->chown(path, uid, gid); - return result.to_fusestatus(); + return fs->chown(path, uid, gid); } -static int fs_truncate(char const * path, off_t raw_size, fuse_file_info * info) +static int fs_truncate(char const * path, off_t size, fuse_file_info * info) { auto * const fs = fs_get_filesystem(); - auto const size = static_cast(raw_size); auto const handle = fs_get_handle(info); - auto const result = fs->truncate(path, size, handle); - return result.to_fusestatus(); + return fs->truncate(path, size, handle); } static int fs_fsync(char const * path, int isdatasync, fuse_file_info * info) @@ -124,36 +110,30 @@ static int fs_fsync(char const * path, int isdatasync, fuse_file_info * info) bool const is_datasync = (is_datasync != 0); auto const handle = fs_get_handle(info); - auto const result = fs->fsync(path, is_datasync, handle); - return result.to_fusestatus(); + return fs->fsync(path, is_datasync, handle); } static int fs_open(char const * path, fuse_file_info * info) { auto * const fs = fs_get_filesystem(); - auto const flags = webfuse::openflags::from_int(info->flags); + auto const flags = info->flags; - auto const result = fs->open(path, flags, info->fh); - return result.to_fusestatus(); + return fs->open(path, flags, info->fh); } -static int fs_mknod(char const * path, mode_t raw_mode, dev_t raw_rdev) +static int fs_mknod(char const * path, mode_t mode, dev_t raw_rdev) { auto * const fs = fs_get_filesystem(); - auto const mode = webfuse::filemode::from_mode(raw_mode); auto const rdev = static_cast(raw_rdev); - auto const result = fs->mknod(path, mode, rdev); - return result.to_fusestatus(); + return fs->mknod(path, mode, rdev); } -static int fs_create(char const * path, mode_t raw_mode, fuse_file_info * info) +static int fs_create(char const * path, mode_t mode, fuse_file_info * info) { auto * const fs = fs_get_filesystem(); - auto const mode = webfuse::filemode::from_mode(raw_mode); - auto const result = fs->create(path, mode, info->fh); - return result.to_fusestatus(); + return fs->create(path, mode, info->fh); } static int fs_release(char const * path, fuse_file_info * info) @@ -161,15 +141,13 @@ static int fs_release(char const * path, fuse_file_info * info) auto * const fs = fs_get_filesystem(); auto const handle = fs_get_handle(info); - auto const result = fs->release(path, handle); - return result.to_fusestatus(); + return fs->release(path, handle); } static int fs_unlink(char const * path) { auto * const fs = fs_get_filesystem(); - auto const result = fs->unlink(path); - return result.to_fusestatus(); + return fs->unlink(path); } static int fs_read(char const * path, char * buffer, @@ -180,8 +158,7 @@ static int fs_read(char const * path, char * buffer, auto const offset = static_cast(raw_offset); auto const handle = fs_get_handle(info); - auto const result = fs->read(path, buffer, buffer_size, offset, handle); - return result.to_fusestatus(); + return fs->read(path, buffer, buffer_size, offset, handle); } static int fs_write(char const * path, char const * buffer, @@ -192,17 +169,13 @@ static int fs_write(char const * path, char const * buffer, auto const offset = static_cast(raw_offset); auto const handle = fs_get_handle(info); - auto const result = fs->write(path, buffer, buffer_size, offset, handle); - return result.to_fusestatus(); + return fs->write(path, buffer, buffer_size, offset, handle); } -static int fs_mkdir(char const * path, mode_t raw_mode) +static int fs_mkdir(char const * path, mode_t mode) { auto * const fs = fs_get_filesystem(); - auto const mode = webfuse::filemode::from_mode(raw_mode); - - auto const result = fs->mkdir(path, mode); - return result.to_fusestatus(); + return fs->mkdir(path, mode); } static int fs_readdir(char const * path, void * buffer, @@ -213,7 +186,7 @@ static int fs_readdir(char const * path, void * buffer, auto handle = fs_get_handle(info); std::vector names; auto const result = fs->readdir(path, names, handle); - if (result.is_good()) + if (0 == result) { filler(buffer, ".", nullptr, 0, static_cast(0)); filler(buffer, "..", nullptr, 0, static_cast(0)); @@ -223,26 +196,19 @@ static int fs_readdir(char const * path, void * buffer, } } - return result.to_fusestatus(); + return result; } static int fs_rmdir(char const * path) { auto * const fs = fs_get_filesystem(); - auto const result = fs->rmdir(path); - return result.to_fusestatus(); + return fs->rmdir(path); } static int fs_statfs(char const * path, struct statvfs * buffer) { auto * const fs = fs_get_filesystem(); - webfuse::filesystem_statistics statistics(*buffer); - - auto const result = fs->statfs(path, statistics); - statistics.copy_to(*buffer); - - return result.to_fusestatus(); - + return fs->statfs(path, buffer); } } diff --git a/src/webfuse/ws/message.hpp b/src/webfuse/ws/message.hpp deleted file mode 100644 index 7fb4f6f..0000000 --- a/src/webfuse/ws/message.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef WEBFUSE_MESSAGEBUILDER_HPP -#define WEBFUSE_MESSAGEBUILDER_HPP - -#include "webfuse/message_type.hpp" - -#include -#include -#include - -namespace webfuse -{ - -class message -{ - message(message const &) = delete; - message& operator=(message const &) = delete; -public: - explicit message(message_type msg_type); - ~message() = default; - message(message && other); - message& operator=(message && other); - - void set_id(uint32_t value); - uint32_t get_id() const; - - void add_bool(bool value); - void add_u8(uint8_t value); - void add_i8(int8_t value); - void add_i32(int32_t value); - void add_u32(uint32_t value); - void add_u64(uint64_t value); - void add_str(std::string const &value); - void add_data(char const * buffer, size_t size); - void add_strings(std::vector const & list); - - unsigned char * get_data(size_t &size); - -private: - uint32_t id; - std::vector data; -}; - -} - -#endif diff --git a/src/webfuse/ws/messagereader.cpp b/src/webfuse/ws/messagereader.cpp new file mode 100644 index 0000000..b073cb8 --- /dev/null +++ b/src/webfuse/ws/messagereader.cpp @@ -0,0 +1,158 @@ +#include "webfuse/ws/messagereader.hpp" +#include "webfuse/filesystem/status.hpp" +#include "webfuse/filesystem/fileattributes.hpp" +#include "webfuse/filesystem/filemode.hpp" + +#include + +namespace webfuse +{ + +messagereader::messagereader(std::string & value) +: data(std::move(value)) +, pos(0) +{ +} + +messagereader::messagereader(messagereader && other) +{ + this->data = std::move(other.data); + this->pos = other.pos; +} + +messagereader& messagereader::operator=(messagereader && other) +{ + if (this != &other) + { + this->data = std::move(other.data); + this->pos = other.pos; + } + + return *this; +} + + +int messagereader::read_result() +{ + status value(read_i32()); + return value.to_fusestatus(); +} + +void messagereader::read_attr(struct stat * attr) +{ + attr->st_ino = static_cast(read_u64()); + attr->st_nlink = static_cast(read_u64()); + attr->st_mode = read_mode(); + attr->st_uid = static_cast(read_u32()); + attr->st_gid = static_cast(read_u32()); + attr->st_rdev = static_cast(read_u64()); + attr->st_size = static_cast(read_u64()); + attr->st_blocks = static_cast(read_u64()); + attr->st_atim.tv_sec = static_cast(read_u64()); + attr->st_atim.tv_nsec = static_cast(read_u32()); + attr->st_mtim.tv_sec = static_cast(read_u64()); + attr->st_mtim.tv_nsec = static_cast(read_u32()); + attr->st_ctim.tv_sec = static_cast(read_u64()); + attr->st_ctim.tv_nsec = static_cast(read_u32()); +} + +mode_t messagereader::read_mode() +{ + filemode mode(read_u32()); + return mode.to_mode(); +} + + +uint8_t messagereader::read_u8() +{ + if (pos < data.size()) + { + uint8_t value = static_cast(data[pos]); + pos++; + return value; + } + else + { + throw std::runtime_error("out of bounds"); + } +} + +uint32_t messagereader::read_u32() +{ + if ((pos + 3) < data.size()) + { + uint32_t value = + ((static_cast(data[pos ]) & 0xff) << 24) | + ((static_cast(data[pos + 1]) & 0xff) << 16) | + ((static_cast(data[pos + 2]) & 0xff) << 8) | + ((static_cast(data[pos + 3]) & 0xff) ); + pos += 4; + return value; + } + else + { + throw std::runtime_error("out of bounds"); + } +} + +uint64_t messagereader::read_u64() +{ + if ((pos + 7) < data.size()) + { + uint32_t value = + (static_cast(data[pos ] & 0xff) << 56) | + (static_cast(data[pos + 1] & 0xff) << 48) | + (static_cast(data[pos + 2] & 0xff) << 40) | + (static_cast(data[pos + 3] & 0xff) << 32) | + (static_cast(data[pos + 4] & 0xff) << 24) | + (static_cast(data[pos + 5] & 0xff) << 16) | + (static_cast(data[pos + 6] & 0xff) << 8) | + (static_cast(data[pos + 7] & 0xff) ); + pos += 8; + return value; + } + else + { + throw std::runtime_error("out of bounds"); + } +} + + +int32_t messagereader::read_i32() +{ + uint32_t value = read_u32(); + return static_cast(value); +} + +std::string messagereader::read_str() +{ + return std::move(read_bytes()); +} + +std::string messagereader::read_bytes() +{ + uint32_t size = read_u32(); + if ((pos + size) <= data.size()) + { + std::string const value(&data[pos], size); + pos += size; + return std::move(value); + } + else + { + throw std::runtime_error("out of bounds"); + } +} + +void messagereader::read_strings(std::vector &entries) +{ + uint32_t const count = read_u32(); + for(uint32_t i = 0; i < count; i++) + { + std::string entry = read_str(); + entries.push_back(entry); + } +} + + +} \ No newline at end of file diff --git a/src/webfuse/ws/messagereader.hpp b/src/webfuse/ws/messagereader.hpp index c62b8b6..6cdceeb 100644 --- a/src/webfuse/ws/messagereader.hpp +++ b/src/webfuse/ws/messagereader.hpp @@ -1,17 +1,43 @@ #ifndef WEBFUSE_MESSAGEREADER_HPP #define WEBFUSE_MESSAGEREADER_HPP +#include +#include +#include + +#include #include +#include namespace webfuse { class messagereader { - + messagereader(messagereader const &) = delete; + messagereader& operator=(messagereader const &) = delete; public: - explicit messagereader(std::string && value); + explicit messagereader(std::string & value); ~messagereader() = default; + messagereader(messagereader && other); + messagereader& operator=(messagereader && other); + + int read_result(); + void read_attr(struct stat * attr); + mode_t read_mode(); + + uint8_t read_u8(); + uint32_t read_u32(); + uint64_t read_u64(); + + int32_t read_i32(); + + std::string read_str(); + std::string read_bytes(); + + void read_strings(std::vector &entries); + + private: std::string data; diff --git a/src/webfuse/ws/message.cpp b/src/webfuse/ws/messagewriter.cpp similarity index 61% rename from src/webfuse/ws/message.cpp rename to src/webfuse/ws/messagewriter.cpp index 77e45ec..86822bb 100644 --- a/src/webfuse/ws/message.cpp +++ b/src/webfuse/ws/messagewriter.cpp @@ -1,24 +1,26 @@ -#include "message.hpp" +#include "webfuse/ws/messagewriter.hpp" +#include "webfuse/filesystem/accessmode.hpp" + #include namespace webfuse { -message::message(message_type msg_type) +messagewriter::messagewriter(message_type msg_type) : id(0) , data(LWS_PRE) { - add_u32(0); - add_u8(static_cast(msg_type)); + write_u32(0); + write_u8(static_cast(msg_type)); } -message::message(message && other) +messagewriter::messagewriter(messagewriter && other) { this->id = other.id; this->data = std::move(other.data); } -message& message::operator=(message && other) +messagewriter& messagewriter::operator=(messagewriter && other) { if (this != &other) { @@ -29,41 +31,41 @@ message& message::operator=(message && other) return *this; } -void message::set_id(uint32_t value) +void messagewriter::set_id(uint32_t value) { - id = id; + id = value; data[LWS_PRE ] = (id >> 24) & 0xff; data[LWS_PRE + 1] = (id >> 16) & 0xff; data[LWS_PRE + 2] = (id >> 8) & 0xff; data[LWS_PRE + 3] = id & 0xff; } -uint32_t message::get_id() const +uint32_t messagewriter::get_id() const { return id; } -void message::add_bool(bool value) +void messagewriter::write_bool(bool value) { data.push_back(value ? 0x01 : 0x00); } -void message::add_u8(uint8_t value) +void messagewriter::write_u8(uint8_t value) { data.push_back(value); } -void message::add_i8(int8_t value) +void messagewriter::write_i8(int8_t value) { data.push_back(static_cast(value)); } -void message::add_i32(int32_t value) +void messagewriter::write_i32(int32_t value) { - add_u32((static_cast(value))); + write_u32((static_cast(value))); } -void message::add_u32(uint32_t value) +void messagewriter::write_u32(uint32_t value) { auto const offset = data.size(); data.resize(offset + 4); @@ -73,7 +75,7 @@ void message::add_u32(uint32_t value) data[offset + 3] = value & 0xff; } -void message::add_u64(uint64_t value) +void messagewriter::write_u64(uint64_t value) { auto const offset = data.size(); data.resize(offset + 8); @@ -87,15 +89,15 @@ void message::add_u64(uint64_t value) data[offset + 7] = value & 0xff; } -void message::add_str(std::string const &value) +void messagewriter::write_str(std::string const &value) { - add_data(value.data(), value.size()); + write_data(value.data(), value.size()); } -void message::add_data(char const * buffer, size_t size) +void messagewriter::write_data(char const * buffer, size_t size) { uint32_t const effective_size = size & 0xffffffff; - add_u32(effective_size); + write_u32(effective_size); if (size > 0) { @@ -107,17 +109,24 @@ void message::add_data(char const * buffer, size_t size) } } -void message::add_strings(std::vector const & list) +void messagewriter::write_strings(std::vector const & list) { uint32_t const count = list.size() & 0xffffffff; - add_u32(count); + write_u32(count); for (auto const & item: list) { - add_str(item); + write_str(item); } } -unsigned char * message::get_data(size_t &size) +void messagewriter::write_access_mode(int value) +{ + access_mode mode = access_mode::from_int(value); + write_i8(mode); +} + + +unsigned char * messagewriter::get_data(size_t &size) { size = data.size() - LWS_PRE; void * result = reinterpret_cast(&data.data()[LWS_PRE]); diff --git a/src/webfuse/ws/messagewriter.hpp b/src/webfuse/ws/messagewriter.hpp new file mode 100644 index 0000000..dc5e30a --- /dev/null +++ b/src/webfuse/ws/messagewriter.hpp @@ -0,0 +1,47 @@ +#ifndef WEBFUSE_MESSAGEWRITER_HPP +#define WEBFUSE_MESSAGEWRITER_HPP + +#include "webfuse/message_type.hpp" + +#include +#include +#include + +namespace webfuse +{ + +class messagewriter +{ + messagewriter(messagewriter const &) = delete; + messagewriter& operator=(messagewriter const &) = delete; +public: + explicit messagewriter(message_type msg_type); + ~messagewriter() = default; + messagewriter(messagewriter && other); + messagewriter& operator=(messagewriter && other); + + void set_id(uint32_t value); + uint32_t get_id() const; + + void write_bool(bool value); + void write_u8(uint8_t value); + void write_i8(int8_t value); + void write_i32(int32_t value); + void write_u32(uint32_t value); + void write_u64(uint64_t value); + void write_str(std::string const &value); + void write_data(char const * buffer, size_t size); + void write_strings(std::vector const & list); + + void write_access_mode(int value); + + unsigned char * get_data(size_t &size); + +private: + uint32_t id; + std::vector data; +}; + +} + +#endif diff --git a/src/webfuse/ws/server.cpp b/src/webfuse/ws/server.cpp index 42eb4c2..499624a 100644 --- a/src/webfuse/ws/server.cpp +++ b/src/webfuse/ws/server.cpp @@ -1,5 +1,4 @@ #include "webfuse/ws/server.hpp" -#include "webfuse/ws/message.hpp" #include @@ -25,10 +24,12 @@ namespace struct user_data { struct lws * connection = nullptr; + std::string current_message; std::mutex mut; - std::queue requests; - std::unordered_map> pending_responses; + uint32_t id = 0; + std::queue requests; + std::unordered_map> pending_responses; }; } @@ -68,11 +69,49 @@ static int ws_server_callback(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_RECEIVE: std::cout << "lws: receive "<< std::endl; + { + auto * fragment = reinterpret_cast(in); + data->current_message.append(fragment, len); + if (lws_is_final_fragment(wsi)) + { + try + { + webfuse::messagereader reader(data->current_message); + uint32_t id = reader.read_u32(); + uint8_t message_type = reader.read_u8(); + + std::lock_guard lock(data->mut); + auto it = data->pending_responses.find(id); + if (it != data->pending_responses.end()) + { + std::cout << "propagate message" << std::endl; + it->second.set_value(std::move(reader)); + data->pending_responses.erase(it); + } + else + { + // ToDo: log request not found + std::cout << "warning: request not found: id=" << id << std::endl; + for(auto const & entry: data->pending_responses) + { + std::cout << "\t" << entry.first << std::endl; + } + } + } + catch(...) + { + // ToDo: log invalid message + std::cout << "warning: invalid message" << std::endl; + } + + + } + } break; case LWS_CALLBACK_SERVER_WRITEABLE: std::cout << "lws: server writable "<< std::endl; { - webfuse::message msg(webfuse::message_type::access_req); + webfuse::messagewriter writer(webfuse::message_type::access_req); bool has_msg = false; bool has_more = false; @@ -82,7 +121,7 @@ static int ws_server_callback(struct lws *wsi, enum lws_callback_reasons reason, if (has_msg) { has_msg = true; - msg = std::move(data->requests.front()); + writer = std::move(data->requests.front()); data->requests.pop(); has_more = !(data->requests.empty()); @@ -92,7 +131,7 @@ static int ws_server_callback(struct lws *wsi, enum lws_callback_reasons reason, if (has_msg) { size_t size; - unsigned char * raw_data = msg.get_data(size); + unsigned char * raw_data = writer.get_data(size); int const rc = lws_write(data->connection, raw_data, size, LWS_WRITE_BINARY); } @@ -148,11 +187,12 @@ public: { if (nullptr != data.connection) { + std::cout << "request write" << std::endl; lws_callback_on_writable(data.connection); } else { - data.requests = std::move(std::queue()); + data.requests = std::move(std::queue()); data.pending_responses.clear(); } } @@ -172,6 +212,16 @@ public: lws_context_destroy(context); } + uint32_t next_id() + { + data.id++; + if (0 == data.id) + { + data.id = 1; + } + return data.id; + } + std::thread thread; std::atomic shutdown_requested; lws_protocols protocols[2]; @@ -209,26 +259,27 @@ ws_server& ws_server::operator=(ws_server && other) return *this; } -void ws_server::perform(message msg) +messagereader ws_server::perform(messagewriter writer) { - std::future f; + std::future f; { - std::promise p; + std::promise p; f = p.get_future(); std::lock_guard lock(d->data.mut); - d->data.requests.emplace(std::move(msg)); - d->data.pending_responses.emplace(42, std::move(p)); + uint32_t id = d->next_id(); + writer.set_id(id); + d->data.requests.emplace(std::move(writer)); + d->data.pending_responses.emplace(id, std::move(p)); } lws_cancel_service(d->context); - if(std::future_status::timeout == f.wait_for(std::chrono::seconds(1))) + if(std::future_status::timeout == f.wait_for(std::chrono::seconds(10))) { throw std::runtime_error("timeout"); } - std::string resp = f.get(); - throw std::runtime_error("not implemented"); + return std::move(f.get()); } diff --git a/src/webfuse/ws/server.hpp b/src/webfuse/ws/server.hpp index c040fc9..84766b2 100644 --- a/src/webfuse/ws/server.hpp +++ b/src/webfuse/ws/server.hpp @@ -2,7 +2,8 @@ #define WEBFUSE_WSSERVER_HPP #include "webfuse/ws/config.hpp" -#include "webfuse/ws/message.hpp" +#include "webfuse/ws/messagewriter.hpp" +#include "webfuse/ws/messagereader.hpp" #include #include @@ -21,7 +22,7 @@ public: ws_server(ws_server && other); ws_server& operator=(ws_server && other); - void perform(message msg); + messagereader perform(messagewriter writer); private: class detail; detail * d;