1
0
mirror of https://github.com/falk-werner/webfuse synced 2025-06-13 12:54:15 +00:00

allow clients to register filesystems

This commit is contained in:
Falk Werner 2019-04-13 21:44:53 +02:00
parent 6418d2c091
commit 9345f947cc
10 changed files with 217 additions and 63 deletions

View File

@ -1,5 +1,6 @@
export class ConnectionView {
constructor(client) {
constructor(client, provider) {
this._provider = provider;
this._client = client;
this._client.onopen = () => { this._onConnectionOpened(); };
this._client.onclose = () => { this._onConnectionClosed(); };
@ -73,6 +74,7 @@ export class ConnectionView {
}
_onConnectionOpened() {
this._client.addProvider("test", this._provider);
this.connectButton.value = "disconnect";
}

View File

@ -17,8 +17,8 @@ function startup() {
"say_hello.sh": { inode: 3, mode: mode("0555"), type: "file", contents: "#!/bin/sh\necho hello\n"}
}
});
const client = new Client(provider);
const connectionView = new ConnectionView(client);
const client = new Client();
const connectionView = new ConnectionView(client, provider);
document.getElementById('connection').appendChild(connectionView.element);
}

View File

@ -4,7 +4,7 @@ export class Client {
static get _PROTOCOL() { return "fs"; }
constructor(provider) {
this._provider = provider;
this._provider = { };
this._ws = null;
this.onopen = () => { };
this.onclose = () => { };
@ -34,6 +34,17 @@ export class Client {
this._ws.send(JSON.stringify(request));
}
addProvider(name, provider) {
this._provider = provider;
const request = {
"method": "add_filesystem",
"params": [name],
"id": 23
};
this._ws.send(JSON.stringify(request));
}
disconnect() {
if (this._ws) {
this._ws.close();

View File

@ -1,5 +1,8 @@
#include "webfuse/adapter/impl/filesystem.h"
#include "webfuse/adapter/impl/operations.h"
#include "webfuse/adapter/impl/session.h"
#include <libwebsockets.h>
#include <stdlib.h>
#include <stddef.h>
@ -16,6 +19,31 @@ static struct fuse_lowlevel_ops const filesystem_operations =
.read = &wf_impl_operation_read
};
struct wf_impl_filesystem * wf_impl_filesystem_create(
struct wf_impl_session * session,
char const * mount_point)
{
struct wf_impl_filesystem * filesystem = malloc(sizeof(struct wf_impl_filesystem));
if (NULL != filesystem)
{
bool success = wf_impl_filesystem_init(filesystem, session, mount_point);
if (!success)
{
free(filesystem);
filesystem = NULL;
}
}
return filesystem;
}
void wf_impl_filesystem_dispose(
struct wf_impl_filesystem * filesystem)
{
wf_impl_filesystem_cleanup(filesystem);
free(filesystem);
}
bool wf_impl_filesystem_init(
struct wf_impl_filesystem * filesystem,
@ -23,6 +51,7 @@ bool wf_impl_filesystem_init(
char const * mount_point)
{
bool result = false;
wf_dlist_item_init(&filesystem->item);
char * argv[] = {"", NULL};
filesystem->args.argc = 1;
@ -43,6 +72,21 @@ bool wf_impl_filesystem_init(
result = (0 == fuse_session_mount(filesystem->session, mount_point));
}
if (result)
{
lws_sock_file_fd_type fd;
fd.filefd = fuse_session_fd(filesystem->session);
struct lws_protocols const * protocol = lws_get_protocol(session->wsi);
filesystem->wsi = lws_adopt_descriptor_vhost(lws_get_vhost(session->wsi), LWS_ADOPT_RAW_FILE_DESC, fd, protocol->name, session->wsi);
if (NULL == filesystem->wsi)
{
wf_impl_filesystem_cleanup(filesystem);
result = false;
}
}
return result;
}

View File

@ -7,6 +7,7 @@
#include "webfuse/adapter/impl/fuse_wrapper.h"
#include "webfuse/adapter/impl/operations.h"
#include "webfuse/core/dlist.h"
#ifdef __cplusplus
extern "C"
@ -14,15 +15,25 @@ extern "C"
#endif
struct wf_impl_session;
struct lws;
struct wf_impl_filesystem
{
struct wf_dlist_item item;
struct fuse_args args;
struct fuse_session * session;
struct fuse_buf buffer;
struct wf_impl_operations_context user_data;
struct lws * wsi;
};
extern struct wf_impl_filesystem * wf_impl_filesystem_create(
struct wf_impl_session * session,
char const * mount_point);
extern void wf_impl_filesystem_dispose(
struct wf_impl_filesystem * filesystem);
extern bool wf_impl_filesystem_init(
struct wf_impl_filesystem * filesystem,
struct wf_impl_session * session,

View File

@ -31,8 +31,7 @@ static int wf_impl_server_protocol_callback(
&protocol->authenticators,
&protocol->timeout_manager,
&protocol->server,
protocol->mount_point,
ws_protocol->name);
protocol->mount_point);
if (NULL != session)
{
@ -57,7 +56,7 @@ static int wf_impl_server_protocol_callback(
case LWS_CALLBACK_RAW_RX_FILE:
if (NULL != session)
{
wf_impl_filesystem_process_request(&session->filesystem);
wf_impl_session_process_filesystem_request(session, wsi);
}
break;
default:
@ -130,6 +129,45 @@ static void wf_impl_server_protocol_authenticate(
}
}
static void wf_impl_server_protocol_add_filesystem(
struct wf_impl_jsonrpc_request * request,
char const * WF_UNUSED_PARAM(method_name),
json_t * params,
void * WF_UNUSED_PARAM(user_data))
{
struct wf_impl_session * session = wf_impl_jsonrpc_request_get_userdata(request);
wf_status status = (session->is_authenticated) ? WF_GOOD : WF_BAD_ACCESS_DENIED;
char const * name = NULL;
if (WF_GOOD == status)
{
json_t * name_holder = json_array_get(params, 0);
if (json_is_string(name_holder))
{
name = json_string_value(name_holder);
bool const success = wf_impl_session_add_filesystem(session, name);
if (!success)
{
status = WF_BAD;
}
}
}
if (WF_GOOD == status)
{
json_t * result = json_object();
json_object_set_new(result, "id", json_string(name));
wf_impl_jsonrpc_respond(request, result);
}
else
{
wf_impl_jsonrpc_respond_error(request, status);
}
}
void wf_impl_server_protocol_init(
struct wf_server_protocol * protocol,
char * mount_point)
@ -142,6 +180,7 @@ void wf_impl_server_protocol_init(
wf_impl_jsonrpc_server_init(&protocol->server);
wf_impl_jsonrpc_server_add(&protocol->server, "authenticate", &wf_impl_server_protocol_authenticate, protocol);
wf_impl_jsonrpc_server_add(&protocol->server, "add_filesystem", &wf_impl_server_protocol_add_filesystem, protocol);
}
void wf_impl_server_protocol_cleanup(

View File

@ -6,6 +6,11 @@
#include "webfuse/adapter/impl/jsonrpc/request.h"
#include "webfuse/adapter/impl/jsonrpc/response.h"
#include "webfuse/core/container_of.h"
#include "webfuse/core/util.h"
#include <uuid/uuid.h>
#include <libwebsockets.h>
#include <stddef.h>
#include <stdlib.h>
@ -40,66 +45,48 @@ struct wf_impl_session * wf_impl_session_create(
struct wf_impl_authenticators * authenticators,
struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server,
char const * mount_point,
char const * protocol_name)
char const * mount_point)
{
static int session_id = 0;
struct wf_impl_session * session = malloc(sizeof(struct wf_impl_session));
if (NULL != session)
{
snprintf(session->mount_point, PATH_MAX, "%s/%d", mount_point, session_id);
session_id++;
mkdir(session->mount_point, 0755);
wf_dlist_item_init(&session->item);
wf_dlist_init(&session->filesystems);
session->mount_point = strdup(mount_point);
session->wsi = wsi;
session->is_authenticated = false;
session->authenticators = authenticators;
session->server = server;
wf_impl_jsonrpc_proxy_init(&session->rpc, timeout_manager, &wf_impl_session_send, session);
wf_message_queue_init(&session->queue);
bool success = wf_impl_filesystem_init(&session->filesystem, session, session->mount_point);
if (success)
{
lws_sock_file_fd_type fd;
fd.filefd = wf_impl_filesystem_get_fd(&session->filesystem);
session->wsi_fuse = lws_adopt_descriptor_vhost(lws_get_vhost(wsi), LWS_ADOPT_RAW_FILE_DESC, fd, protocol_name, wsi);
if (NULL == session->wsi_fuse)
{
success = false;
fprintf(stderr, "error: unable to adopt fd");
}
}
if (!success)
{
rmdir(session->mount_point);
wf_impl_jsonrpc_proxy_cleanup(&session->rpc);
wf_message_queue_cleanup(&session->queue);
free(session);
session = NULL;
}
}
return session;
}
static void wf_impl_session_cleanup_filesystem(
struct wf_dlist_item * item,
void * WF_UNUSED_PARAM(user_data))
{
struct wf_impl_filesystem * filesystem = WF_CONTAINER_OF(item, struct wf_impl_filesystem, item);
wf_impl_filesystem_dispose(filesystem);
}
void wf_impl_session_dispose(
struct wf_impl_session * session)
{
wf_impl_filesystem_cleanup(&session->filesystem);
rmdir(session->mount_point);
wf_dlist_cleanup(&session->filesystems, &wf_impl_session_cleanup_filesystem, NULL);
wf_impl_jsonrpc_proxy_cleanup(&session->rpc);
wf_message_queue_cleanup(&session->queue);
session->is_authenticated = false;
session->wsi = NULL;
session->wsi_fuse = NULL;
session->authenticators = NULL;
session->server = NULL;
free(session->mount_point);
free(session);
}
@ -112,6 +99,25 @@ bool wf_impl_session_authenticate(
return session->is_authenticated;
}
bool wf_impl_session_add_filesystem(
struct wf_impl_session * session,
char const * name)
{
uuid_t uuid;
uuid_generate(uuid);
char id[UUID_STR_LEN];
uuid_unparse(uuid, id);
char mount_point[PATH_MAX];
snprintf(mount_point, PATH_MAX, "%s/%s/%s", session->mount_point, name, id);
mkdir(mount_point, 0755);
struct wf_impl_filesystem * filesystem = wf_impl_filesystem_create(session, mount_point);
wf_dlist_prepend(&session->filesystems, &filesystem->item);
return (NULL != filesystem);
}
void wf_impl_session_onwritable(
struct wf_impl_session * session)
{
@ -150,3 +156,47 @@ void wf_impl_session_receive(
}
}
static struct wf_impl_filesystem * wf_impl_session_get_filesystem(
struct wf_impl_session * session,
struct lws * wsi)
{
struct wf_impl_filesystem * filesystem = WF_CONTAINER_OF(session->filesystems.first, struct wf_impl_filesystem, item);
while (NULL != filesystem)
{
if (wsi == filesystem->wsi)
{
break;
}
else
{
filesystem = WF_CONTAINER_OF(filesystem->item.next, struct wf_impl_filesystem, item);
}
}
return filesystem;
}
bool wf_impl_session_contains_wsi(
struct wf_dlist_item * item,
void * user_data)
{
struct lws * wsi = user_data;
struct wf_impl_session * session = WF_CONTAINER_OF(item, struct wf_impl_session, item);
bool const result = (NULL != wsi) && ((wsi == session->wsi) || (NULL != wf_impl_session_get_filesystem(session, wsi)));
return result;
}
void wf_impl_session_process_filesystem_request(
struct wf_impl_session * session,
struct lws * wsi)
{
struct wf_impl_filesystem * filesystem = wf_impl_session_get_filesystem(session, wsi);
if (NULL != filesystem)
{
wf_impl_filesystem_process_request(filesystem);
}
}

View File

@ -9,8 +9,6 @@
using std::size_t;
#endif
#include <limits.h>
#include "webfuse/core/message_queue.h"
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/adapter/impl/jsonrpc/server.h"
@ -31,15 +29,14 @@ struct wf_impl_timeout_manager;
struct wf_impl_session
{
struct wf_dlist_item item;
char mount_point[PATH_MAX];
char * mount_point;
struct lws * wsi;
struct lws * wsi_fuse;
bool is_authenticated;
struct wf_message_queue queue;
struct wf_impl_filesystem filesystem;
struct wf_impl_authenticators * authenticators;
struct wf_impl_jsonrpc_server * server;
struct wf_impl_jsonrpc_proxy rpc;
struct wf_dlist filesystems;
};
extern struct wf_impl_session * wf_impl_session_create(
@ -47,8 +44,7 @@ extern struct wf_impl_session * wf_impl_session_create(
struct wf_impl_authenticators * authenticators,
struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server,
char const * mount_point,
char const * protocol_name);
char const * mount_point);
extern void wf_impl_session_dispose(
struct wf_impl_session * session);
@ -57,6 +53,10 @@ extern bool wf_impl_session_authenticate(
struct wf_impl_session * session,
struct wf_credentials * creds);
extern bool wf_impl_session_add_filesystem(
struct wf_impl_session * session,
char const * name);
extern void wf_impl_session_receive(
struct wf_impl_session * session,
char const * data,
@ -65,6 +65,15 @@ extern void wf_impl_session_receive(
extern void wf_impl_session_onwritable(
struct wf_impl_session * session);
extern bool wf_impl_session_contains_wsi(
struct wf_dlist_item * item,
void * user_data);
extern void wf_impl_session_process_filesystem_request(
struct wf_impl_session * session,
struct lws * wsi);
#ifdef __cplusplus
}
#endif

View File

@ -33,11 +33,10 @@ struct wf_impl_session * wf_impl_session_manager_add(
struct wf_impl_authenticators * authenticators,
struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server,
char const * mount_point,
char const * protocol_name)
char const * mount_point)
{
struct wf_impl_session * session = wf_impl_session_create(
wsi, authenticators, timeout_manager, server, mount_point, protocol_name);
wsi, authenticators, timeout_manager, server, mount_point);
if (NULL != session)
{
wf_dlist_prepend(&manager->sessions, &session->item);
@ -46,23 +45,13 @@ struct wf_impl_session * wf_impl_session_manager_add(
return session;
}
static bool wf_impl_session_manager_get_predicate(
struct wf_dlist_item * item,
void * user_data)
{
struct lws * wsi = user_data;
struct wf_impl_session * session = WF_CONTAINER_OF(item, struct wf_impl_session, item);
return ((wsi == session->wsi) || (wsi == session->wsi_fuse));
}
struct wf_impl_session * wf_impl_session_manager_get(
struct wf_impl_session_manager * manager,
struct lws * wsi)
{
struct wf_impl_session * session = NULL;
struct wf_dlist_item * item = wf_dlist_find_first(
&manager->sessions, &wf_impl_session_manager_get_predicate, wsi);
&manager->sessions, &wf_impl_session_contains_wsi, wsi);
if (NULL != item)
{
session = WF_CONTAINER_OF(item, struct wf_impl_session, item);

View File

@ -35,8 +35,7 @@ extern struct wf_impl_session * wf_impl_session_manager_add(
struct wf_impl_authenticators * authenticators,
struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server,
char const * mount_point,
char const * protocol_name);
char const * mount_point);
extern struct wf_impl_session * wf_impl_session_manager_get(
struct wf_impl_session_manager * manager,