1
0
mirror of https://github.com/falk-werner/webfuse synced 2026-03-02 03:40:24 +00:00

implemented basic request

This commit is contained in:
Falk Werner
2022-11-19 22:57:32 +01:00
parent bc024481f9
commit 7924fa1191
10 changed files with 578 additions and 63 deletions

View File

@@ -18,8 +18,10 @@ status filesystem::access(std::string const & path, access_mode mode)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::access_req);
req.add_str(path);
req.add_i8(mode);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -32,8 +34,8 @@ status filesystem::getattr(std::string const & path, file_attributes & attr)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::getattr_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -46,8 +48,8 @@ status filesystem::readlink(std::string const & path, std::string & out)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::readlink_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -60,8 +62,8 @@ status filesystem::symlink(std::string const & target, std::string const & linkp
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::symlink_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -74,8 +76,8 @@ status filesystem::link(std::string const & old_path, std::string const & new_pa
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::link_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -88,8 +90,8 @@ status filesystem::rename(std::string const & old_path, std::string const & new_
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::rename_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -102,8 +104,8 @@ status filesystem::chmod(std::string const & path, filemode mode)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::chmod_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -116,8 +118,8 @@ status filesystem::chown(std::string const & path, user_id uid, group_id gid)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::chown_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -130,8 +132,8 @@ status filesystem::truncate(std::string const & path, uint64_t offset, filehandl
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::truncate_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -144,8 +146,8 @@ status filesystem::fsync(std::string const & path, bool is_datasync, filehandle
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::fsync_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -158,8 +160,8 @@ status filesystem::open(std::string const & path, openflags flags, filehandle &
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::open_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -172,8 +174,8 @@ status filesystem::mknod(std::string const & path, filemode mode, uint64_t rdev)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::mknod_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -186,8 +188,8 @@ status filesystem::create(std::string const & path, filemode mode, filehandle &
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::create_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -200,8 +202,8 @@ status filesystem::release(std::string const & path, filehandle handle)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::release_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -214,8 +216,8 @@ status filesystem::unlink(std::string const & path)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::unlink_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -228,8 +230,8 @@ status filesystem::read(std::string const & path, char * buffer, size_t buffer_s
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::read_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -242,8 +244,8 @@ status filesystem::write(std::string const & path, char const * buffer, size_t b
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::write_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -256,8 +258,8 @@ status filesystem::mkdir(std::string const & path, filemode mode)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::mkdir_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -270,8 +272,8 @@ status filesystem::readdir(std::string const & path, std::vector<std::string> &
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::readdir_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -284,8 +286,8 @@ status filesystem::rmdir(std::string const & path)
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::rmdir_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)
@@ -298,8 +300,8 @@ status filesystem::statfs(std::string const & path, filesystem_statistics & stat
{
try
{
std::string req;
auto resp = proxy.perform(req).get();
message req(message_type::statfs_req);
proxy.perform(std::move(req));
return status::bad_enoent;
}
catch(...)

View File

@@ -0,0 +1,37 @@
#ifndef WEBFUSE_MESSAGETYPE_HPP
#define WEBFUSE_MESSAGETYPE_HPP
#include <cinttypes>
namespace webfuse
{
enum class message_type: uint8_t
{
access_req = 0x01,
getattr_req = 0x02,
readlink_req = 0x03,
symlink_req = 0x04,
link_req = 0x05,
rename_req = 0x06,
chmod_req = 0x07,
chown_req = 0x08,
truncate_req = 0x09,
fsync_req = 0x0a,
open_req = 0x0b,
mknod_req = 0x0c,
create_req = 0x0d,
release_req = 0x0e,
unlink_req = 0x0f,
read_req = 0x10,
write_req = 0x11,
mkdir_req = 0x12,
readdir_req = 0x13,
rmdir_req = 0x14,
statfs_req = 0x15
};
}
#endif

129
src/webfuse/ws/message.cpp Normal file
View File

@@ -0,0 +1,129 @@
#include "message.hpp"
#include <libwebsockets.h>
namespace webfuse
{
message::message(message_type msg_type)
: id(0)
, data(LWS_PRE)
{
add_u32(0);
add_u8(static_cast<uint8_t>(msg_type));
}
message::message(message && other)
{
this->id = other.id;
this->data = std::move(other.data);
}
message& message::operator=(message && other)
{
if (this != &other)
{
this->id = other.id;
this->data = std::move(other.data);
}
return *this;
}
void message::set_id(uint32_t value)
{
id = id;
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
{
return id;
}
void message::add_bool(bool value)
{
data.push_back(value ? 0x01 : 0x00);
}
void message::add_u8(uint8_t value)
{
data.push_back(value);
}
void message::add_i8(int8_t value)
{
data.push_back(static_cast<uint8_t>(value));
}
void message::add_i32(int32_t value)
{
add_u32((static_cast<uint32_t>(value)));
}
void message::add_u32(uint32_t value)
{
auto const offset = data.size();
data.resize(offset + 4);
data[offset ] = (value >> 24) & 0xff;
data[offset + 1] = (value >> 16) & 0xff;
data[offset + 2] = (value >> 8) & 0xff;
data[offset + 3] = value & 0xff;
}
void message::add_u64(uint64_t value)
{
auto const offset = data.size();
data.resize(offset + 8);
data[offset ] = (value >> 56) & 0xff;
data[offset + 1] = (value >> 48) & 0xff;
data[offset + 2] = (value >> 40) & 0xff;
data[offset + 3] = (value >> 32) & 0xff;
data[offset + 4] = (value >> 24) & 0xff;
data[offset + 5] = (value >> 16) & 0xff;
data[offset + 6] = (value >> 8) & 0xff;
data[offset + 7] = value & 0xff;
}
void message::add_str(std::string const &value)
{
add_data(value.data(), value.size());
}
void message::add_data(char const * buffer, size_t size)
{
uint32_t const effective_size = size & 0xffffffff;
add_u32(effective_size);
if (size > 0)
{
auto const offset = data.size();
data.resize(offset + effective_size);
void * to = reinterpret_cast<void*>(&data.data()[offset]);
void const * from = reinterpret_cast<void const *>(buffer);
memcpy(to, from, effective_size);
}
}
void message::add_strings(std::vector<std::string> const & list)
{
uint32_t const count = list.size() & 0xffffffff;
add_u32(count);
for (auto const & item: list)
{
add_str(item);
}
}
unsigned char * message::get_data(size_t &size)
{
size = data.size() - LWS_PRE;
void * result = reinterpret_cast<void *>(&data.data()[LWS_PRE]);
return reinterpret_cast<unsigned char *>(result);
}
}

View File

@@ -0,0 +1,45 @@
#ifndef WEBFUSE_MESSAGEBUILDER_HPP
#define WEBFUSE_MESSAGEBUILDER_HPP
#include "webfuse/message_type.hpp"
#include <cinttypes>
#include <string>
#include <vector>
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<std::string> const & list);
unsigned char * get_data(size_t &size);
private:
uint32_t id;
std::vector<uint8_t> data;
};
}
#endif

View File

@@ -0,0 +1,23 @@
#ifndef WEBFUSE_MESSAGEREADER_HPP
#define WEBFUSE_MESSAGEREADER_HPP
#include <string>
namespace webfuse
{
class messagereader
{
public:
explicit messagereader(std::string && value);
~messagereader() = default;
private:
std::string data;
size_t pos;
};
}
#endif

View File

@@ -1,40 +1,108 @@
#include "webfuse/ws/server.hpp"
#include "webfuse/ws/message.hpp"
#include <libwebsockets.h>
#include <cinttypes>
#include <cstring>
#include <iostream>
#include <thread>
#include <atomic>
#include <mutex>
#include <future>
#include <chrono>
#include <stdexcept>
#include <queue>
#include <string>
#include <unordered_map>
namespace
{
struct user_data
{
struct lws * connection = nullptr;
std::mutex mut;
std::queue<webfuse::message> requests;
std::unordered_map<uint32_t, std::promise<std::string>> pending_responses;
};
}
extern "C"
{
static int ws_server_callback(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
auto const * protocol = lws_get_protocol(wsi);
if (nullptr == protocol) { return 0; }
if (&ws_server_callback != protocol->callback) { return 0; }
auto * data = reinterpret_cast<user_data *>(protocol->user);
int result = 0;
switch(reason)
{
case LWS_CALLBACK_PROTOCOL_INIT:
std::cout << "lws: protocol init "<< std::endl;
break;
case LWS_CALLBACK_ESTABLISHED:
std::cout << "lws: established "<< std::endl;
if (nullptr == data->connection)
{
data->connection = wsi;
}
else
{
result = -1;
}
break;
case LWS_CALLBACK_CLOSED:
std::cout << "lws: closed "<< std::endl;
if (wsi == data->connection)
{
data->connection = nullptr;
}
break;
case LWS_CALLBACK_RECEIVE:
std::cout << "lws: receive "<< std::endl;
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
std::cout << "lws: server writable "<< std::endl;
{
webfuse::message msg(webfuse::message_type::access_req);
bool has_msg = false;
bool has_more = false;
{
std::lock_guard lock(data->mut);
has_msg = !(data->requests.empty());
if (has_msg)
{
has_msg = true;
msg = std::move(data->requests.front());
data->requests.pop();
has_more = !(data->requests.empty());
}
}
if (has_msg)
{
size_t size;
unsigned char * raw_data = msg.get_data(size);
int const rc = lws_write(data->connection, raw_data, size, LWS_WRITE_BINARY);
}
}
break;
default:
break;
}
return 0;
return result;
}
@@ -57,7 +125,7 @@ public:
protocols[0].name = "webfuse2";
protocols[0].callback = &ws_server_callback;
protocols[0].per_session_data_size = 0;
protocols[0].user = nullptr;
protocols[0].user = reinterpret_cast<void*>(&data);
memset(reinterpret_cast<void*>(&info), 0, sizeof(info));
info.port = config.port;
@@ -74,6 +142,22 @@ public:
thread = std::thread([this]() {
while (!shutdown_requested)
{
{
std::lock_guard lock(data.mut);
if (!data.requests.empty())
{
if (nullptr != data.connection)
{
lws_callback_on_writable(data.connection);
}
else
{
data.requests = std::move(std::queue<webfuse::message>());
data.pending_responses.clear();
}
}
}
lws_service(context, 0);
}
@@ -93,6 +177,7 @@ public:
lws_protocols protocols[2];
lws_context_creation_info info;
lws_context * context;
user_data data;
};
ws_server::ws_server(ws_config const & config)
@@ -124,20 +209,26 @@ ws_server& ws_server::operator=(ws_server && other)
return *this;
}
std::future<std::string> ws_server::perform(std::string const & req)
void ws_server::perform(message msg)
{
std::promise<std::string> resp;
std::future<std::string> f;
{
std::promise<std::string> p;
f = p.get_future();
try
{
throw std::runtime_error("not implemented");
std::lock_guard lock(d->data.mut);
d->data.requests.emplace(std::move(msg));
d->data.pending_responses.emplace(42, std::move(p));
}
catch (std::exception const & ex)
lws_cancel_service(d->context);
if(std::future_status::timeout == f.wait_for(std::chrono::seconds(1)))
{
resp.set_exception(std::current_exception());
throw std::runtime_error("timeout");
}
return resp.get_future();
std::string resp = f.get();
throw std::runtime_error("not implemented");
}

View File

@@ -2,8 +2,12 @@
#define WEBFUSE_WSSERVER_HPP
#include "webfuse/ws/config.hpp"
#include <future>
#include "webfuse/ws/message.hpp"
#include <vector>
#include <string>
#include <memory>
namespace webfuse
{
@@ -16,7 +20,8 @@ public:
~ws_server();
ws_server(ws_server && other);
ws_server& operator=(ws_server && other);
std::future<std::string> perform(std::string const & req);
void perform(message msg);
private:
class detail;
detail * d;