1
0
mirror of https://github.com/falk-werner/webfuse-provider synced 2026-03-02 04:09:18 +00:00

feat(webfuse): add multiclient support (#23)

* fixes verbosity option when set through command line

* adds support for build type and allows to run gdb in container

* adds missing toolchain headers to project

* renames container macros

* adds gdbserver

* fixes verbosity option when set through command line

* adds support for build type and allows to run gdb in container

* adds missing toolchain headers to project

* renames container macros

* adds gdbserver

* removes language settings, which contains alternating values

* adds wrapper script to launch gdbserver

* fix docker command in wrapper script

* fixes run in dind setup

* replaces docker's init through dump-init

* moves filesystem to session

* fixes verbosity option when set through command line

* adds support for build type and allows to run gdb in container

* renames container macros

* adds gdbserver

* fixes verbosity option when set through command line

* adds support for build type and allows to run gdb in container

* renames container macros

* adds gdbserver

* adds wrapper script to launch gdbserver

* fix docker command in wrapper script

* fixes run in dind setup

* replaces docker's init through dump-init

* moves filesystem to session

* adds container_of

* added dlist

* allows multiple clients to connect

* removes directory when session is closed

* adds dependecy to uuid-dev

* allow clients to register filesystems

* updates documentation

* moves mountpoint handling into filesystem: mountpoints are removed during session cleanup

* adds filesystem name/id to request parameters

* fixes security issue: add_filesystem did not check name

* removes default link, if it is broken

* recreates symlink "default", if filesystem is gone

* updates documentation

* fixes memory leak

* makes authentication work .. again

* updates provider to support changed protocol

* removes execute right of hello.txt

* fixes style issues

* fixes javascript style issues

* fixes flase positive from Flawfinder

* fixes some javascript style issues

* removes use of PATH_MAX

* removes use of GNU extensions in container_of implementation

* ignores findings of flawfinder

* replaces dlist by slist

* removes duplicate implementation of slist (message_queue)
This commit is contained in:
Falk Werner
2019-04-17 22:51:16 +02:00
committed by nosamad
parent 979ff1e689
commit 3a7c064af7
52 changed files with 997 additions and 337 deletions

View File

@@ -1,5 +1,16 @@
#include "webfuse/adapter/impl/filesystem.h"
#include "webfuse/adapter/impl/operations.h"
#include "webfuse/adapter/impl/session.h"
#include "webfuse/core/string.h"
#include <libwebsockets.h>
#include <uuid/uuid.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include <stddef.h>
@@ -16,23 +27,118 @@ static struct fuse_lowlevel_ops const filesystem_operations =
.read = &wf_impl_operation_read
};
static char * wf_impl_filesystem_create_id(void)
{
uuid_t uuid;
uuid_generate(uuid);
char id[UUID_STR_LEN];
uuid_unparse(uuid, id);
bool wf_impl_filesystem_init(
struct wf_impl_filesystem * filesystem,
struct wf_impl_session_manager * session_manager,
char * mount_point)
return strdup(id);
}
static bool wf_impl_filesystem_is_link_broken(char const * path, char const * id)
{
bool result = false;
char buffer[UUID_STR_LEN];
ssize_t count = readlink(path, buffer, UUID_STR_LEN);
if ((0 < count) && (count < UUID_STR_LEN))
{
buffer[count] = '\0';
result = (0 == strcmp(buffer, id));
}
return result;
}
static bool wf_impl_filesystem_link_first_subdir(
char const * link_path,
char const * path)
{
bool result = false;
DIR * dir = opendir(path);
if (NULL != dir)
{
struct dirent * entry = readdir(dir);
while (NULL != entry)
{
if ((DT_DIR == entry->d_type) && ('.' != entry->d_name[0]))
{
symlink(entry->d_name, link_path);
result = true;
break;
}
entry = readdir(dir);
}
closedir(dir);
}
return result;
}
static void wf_impl_filesystem_cleanup(
struct wf_impl_filesystem * filesystem)
{
fuse_session_reset(filesystem->session);
fuse_session_unmount(filesystem->session);
fuse_session_destroy(filesystem->session);
filesystem->session = NULL;
free(filesystem->buffer.mem);
fuse_opt_free_args(&filesystem->args);
rmdir(filesystem->root_path);
if (wf_impl_filesystem_is_link_broken(filesystem->default_path, filesystem->id))
{
unlink(filesystem->default_path);
bool const success = wf_impl_filesystem_link_first_subdir(filesystem->default_path, filesystem->service_path);
if (!success)
{
rmdir(filesystem->service_path);
}
}
free(filesystem->user_data.name);
free(filesystem->id);
free(filesystem->root_path);
free(filesystem->default_path);
free(filesystem->service_path);
}
static bool wf_impl_filesystem_init(
struct wf_impl_filesystem * filesystem,
struct wf_impl_session * session,
char const * name)
{
bool result = false;
char * argv[] = {"", NULL};
filesystem->args.argc = 1;
filesystem->args.argv = argv;
filesystem->args.allocated = 0;
filesystem->user_data.session_manager = session_manager;
filesystem->user_data.session = session;
filesystem->user_data.timeout = 1.0;
filesystem->user_data.name = strdup(name);
memset(&filesystem->buffer, 0, sizeof(struct fuse_buf));
filesystem->service_path = wf_create_string("%s/%s", session->mount_point, name);
mkdir(filesystem->service_path, 0755);
filesystem->id = wf_impl_filesystem_create_id();
filesystem->root_path = wf_create_string("%s/%s/%s", session->mount_point, name, filesystem->id);
mkdir(filesystem->root_path, 0755);
filesystem->default_path = wf_create_string("%s/%s/default", session->mount_point, name);
symlink(filesystem->id, filesystem->default_path);
filesystem->session = fuse_session_new(
&filesystem->args,
&filesystem_operations,
@@ -40,31 +146,50 @@ bool wf_impl_filesystem_init(
&filesystem->user_data);
if (NULL != filesystem->session)
{
result = (0 == fuse_session_mount(filesystem->session, mount_point));
result = (0 == fuse_session_mount(filesystem->session, filesystem->root_path));
}
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;
}
void wf_impl_filesystem_cleanup(
struct wf_impl_filesystem * filesystem)
struct wf_impl_filesystem * wf_impl_filesystem_create(
struct wf_impl_session * session,
char const * name)
{
if (NULL != filesystem->session)
struct wf_impl_filesystem * filesystem = malloc(sizeof(struct wf_impl_filesystem));
if (NULL != filesystem)
{
fuse_session_reset(filesystem->session);
fuse_session_unmount(filesystem->session);
fuse_session_destroy(filesystem->session);
filesystem->session = NULL;
bool success = wf_impl_filesystem_init(filesystem, session, name);
if (!success)
{
free(filesystem);
filesystem = NULL;
}
}
free(filesystem->buffer.mem);
fuse_opt_free_args(&filesystem->args);
return filesystem;
}
int wf_impl_filesystem_get_fd(
void wf_impl_filesystem_dispose(
struct wf_impl_filesystem * filesystem)
{
return fuse_session_fd(filesystem->session);
wf_impl_filesystem_cleanup(filesystem);
free(filesystem);
}
void wf_impl_filesystem_process_request(

View File

@@ -7,31 +7,36 @@
#include "webfuse/adapter/impl/fuse_wrapper.h"
#include "webfuse/adapter/impl/operations.h"
#include "webfuse/core/slist.h"
#ifdef __cplusplus
extern "C"
{
#endif
struct wf_impl_session_manager;
struct wf_impl_session;
struct lws;
struct wf_impl_filesystem
{
struct wf_slist_item item;
struct fuse_args args;
struct fuse_session * session;
struct fuse_buf buffer;
struct wf_impl_operations_context user_data;
struct lws * wsi;
char * name;
char * id;
char * service_path;
char * default_path;
char * root_path;
};
extern bool wf_impl_filesystem_init(
struct wf_impl_filesystem * filesystem,
struct wf_impl_session_manager * session_manager,
char * mount_point);
extern struct wf_impl_filesystem * wf_impl_filesystem_create(
struct wf_impl_session * session,
char const * name);
extern void wf_impl_filesystem_cleanup(
struct wf_impl_filesystem * filesystem);
extern int wf_impl_filesystem_get_fd(
extern void wf_impl_filesystem_dispose(
struct wf_impl_filesystem * filesystem);
extern void wf_impl_filesystem_process_request(

View File

@@ -13,12 +13,12 @@ void wf_impl_operation_close(
struct fuse_file_info * file_info)
{
struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data);
if (NULL != rpc)
{
int handle = (int) (file_info->fh & INT_MAX);
wf_impl_jsonrpc_proxy_notify(rpc, "close", "iii", inode, handle, file_info->flags);
wf_impl_jsonrpc_proxy_notify(rpc, "close", "siii", user_data->name, inode, handle, file_info->flags);
}
fuse_reply_err(request, 0);

View File

@@ -81,7 +81,7 @@ void wf_impl_operation_getattr (
{
struct fuse_ctx const * context = fuse_req_ctx(request);
struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data);
if (NULL != rpc)
{
@@ -91,7 +91,7 @@ void wf_impl_operation_getattr (
getattr_context->gid = context->gid;
getattr_context->timeout = user_data->timeout;
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_getattr_finished, getattr_context, "getattr", "i", inode);
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_getattr_finished, getattr_context, "getattr", "si", user_data->name, inode);
}
else
{

View File

@@ -90,7 +90,7 @@ void wf_impl_operation_lookup (
{
struct fuse_ctx const * context = fuse_req_ctx(request);
struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, parent);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data);
if (NULL != rpc)
{
@@ -100,7 +100,7 @@ void wf_impl_operation_lookup (
lookup_context->gid = context->gid;
lookup_context->timeout = user_data->timeout;
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_lookup_finished, lookup_context, "lookup", "is", (int) (parent & INT_MAX), name);
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_lookup_finished, lookup_context, "lookup", "sis", user_data->name, (int) (parent & INT_MAX), name);
}
else
{

View File

@@ -47,11 +47,11 @@ void wf_impl_operation_open(
struct fuse_file_info * file_info)
{
struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data);
if (NULL != rpc)
{
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_open_finished, request, "open", "ii", inode, file_info->flags);
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_open_finished, request, "open", "sii", user_data->name, inode, file_info->flags);
}
else
{

View File

@@ -87,13 +87,13 @@ void wf_impl_operation_read(
struct fuse_file_info * file_info)
{
struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data);
if (NULL != rpc)
{
int const length = (size <= WF_MAX_READ_LENGTH) ? (int) size : WF_MAX_READ_LENGTH;
int handle = (file_info->fh & INT_MAX);
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_read_finished, request, "read", "iiii", inode, handle, (int) offset, length);
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_read_finished, request, "read", "siiii", user_data->name, inode, handle, (int) offset, length);
}
else
{

View File

@@ -137,7 +137,7 @@ void wf_impl_operation_readdir (
struct fuse_file_info * WF_UNUSED_PARAM(file_info))
{
struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data);
if (NULL != rpc)
{
@@ -146,7 +146,7 @@ void wf_impl_operation_readdir (
readdir_context->size = size;
readdir_context->offset = offset;
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_readdir_finished, readdir_context, "readdir", "i", inode);
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_readdir_finished, readdir_context, "readdir", "si", user_data->name, inode);
}
else
{

View File

@@ -4,13 +4,11 @@
#include <stddef.h>
struct wf_impl_jsonrpc_proxy * wf_impl_operations_context_get_proxy(
struct wf_impl_operations_context * context,
fuse_ino_t inode)
struct wf_impl_operations_context * context)
{
struct wf_impl_jsonrpc_proxy * proxy = NULL;
struct wf_impl_session_manager * session_manger = context->session_manager;
struct wf_impl_session * session = wf_impl_session_manager_get_by_inode(session_manger, inode);
struct wf_impl_session * session = context->session;
if (NULL != session)
{
proxy = &session->rpc;

View File

@@ -7,13 +7,14 @@
extern "C" {
#endif
struct wf_impl_session_manager;
struct wf_impl_session;
struct wf_impl_jsonrpc_proxy;
struct wf_impl_operations_context
{
struct wf_impl_session_manager * session_manager;
struct wf_impl_session * session;
double timeout;
char * name;
};
extern void wf_impl_operation_lookup (
@@ -49,8 +50,7 @@ extern void wf_impl_operation_read(
struct fuse_file_info *fi);
extern struct wf_impl_jsonrpc_proxy * wf_impl_operations_context_get_proxy(
struct wf_impl_operations_context * context,
fuse_ino_t inode);
struct wf_impl_operations_context * context);
#ifdef __cplusplus
}

View File

@@ -108,18 +108,11 @@ struct wf_server * wf_impl_server_create(
server = malloc(sizeof(struct wf_server));
if (NULL != server)
{
if (wf_impl_server_protocol_init(&server->protocol, config->mount_point))
{
server->shutdown_requested = false;
wf_impl_server_config_clone(config, &server->config);
wf_impl_authenticators_move(&server->config.authenticators, &server->protocol.authenticators);
server->context = wf_impl_server_context_create(server);
}
else
{
free(server);
server = NULL;
}
wf_impl_server_protocol_init(&server->protocol, config->mount_point);
server->shutdown_requested = false;
wf_impl_server_config_clone(config, &server->config);
wf_impl_authenticators_move(&server->config.authenticators, &server->protocol.authenticators);
server->context = wf_impl_server_context_create(server);
}
}

View File

@@ -1,12 +1,12 @@
#include "webfuse/adapter/impl/server_protocol.h"
#include <stdlib.h>
#include <ctype.h>
#include <libwebsockets.h>
#include "webfuse/core/message.h"
#include "webfuse/core/util.h"
#include "webfuse/adapter/impl/filesystem.h"
#include "webfuse/adapter/impl/credentials.h"
#include "webfuse/adapter/impl/jsonrpc/request.h"
@@ -25,23 +25,14 @@ static int wf_impl_server_protocol_callback(
switch (reason)
{
case LWS_CALLBACK_PROTOCOL_INIT:
{
lws_sock_file_fd_type fd;
fd.filefd = wf_impl_filesystem_get_fd(&protocol->filesystem);
if (!lws_adopt_descriptor_vhost(lws_get_vhost(wsi), LWS_ADOPT_RAW_FILE_DESC, fd, ws_protocol->name, NULL))
{
fprintf(stderr, "error: unable to adopt fd");
}
}
break;
case LWS_CALLBACK_ESTABLISHED:
session = wf_impl_session_manager_add(
&protocol->session_manager,
wsi,
&protocol->authenticators,
&protocol->timeout_manager,
&protocol->server);
&protocol->server,
protocol->mount_point);
if (NULL != session)
{
@@ -64,7 +55,10 @@ static int wf_impl_server_protocol_callback(
}
break;
case LWS_CALLBACK_RAW_RX_FILE:
wf_impl_filesystem_process_request(&protocol->filesystem);
if (NULL != session)
{
wf_impl_session_process_filesystem_request(session, wsi);
}
break;
default:
break;
@@ -79,11 +73,7 @@ struct wf_server_protocol * wf_impl_server_protocol_create(
struct wf_server_protocol * protocol = malloc(sizeof(struct wf_server_protocol));
if (NULL != protocol)
{
if (!wf_impl_server_protocol_init(protocol, mount_point))
{
free(protocol);
protocol = NULL;
}
wf_impl_server_protocol_init(protocol, mount_point);
}
return protocol;
@@ -140,35 +130,91 @@ static void wf_impl_server_protocol_authenticate(
}
}
bool wf_impl_server_protocol_init(
static bool wf_impl_server_protocol_check_name(char const * value)
{
while ('\0' != *value)
{
char const c = * value;
if (!isalpha(c) && !isdigit(c) && ('_' != c))
{
return false;
}
value++;
}
return true;
}
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);
if (wf_impl_server_protocol_check_name(name))
{
bool const success = wf_impl_session_add_filesystem(session, name);
if (!success)
{
status = WF_BAD;
}
}
else
{
status = WF_BAD_FORMAT;
}
}
else
{
status = WF_BAD_FORMAT;
}
}
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)
{
protocol->mount_point = strdup(mount_point);
wf_impl_timeout_manager_init(&protocol->timeout_manager);
wf_impl_session_manager_init(&protocol->session_manager);
wf_impl_authenticators_init(&protocol->authenticators);
wf_impl_jsonrpc_server_init(&protocol->server);
wf_impl_jsonrpc_server_add(&protocol->server, "authenticate", &wf_impl_server_protocol_authenticate, protocol);
bool const success = wf_impl_filesystem_init(&protocol->filesystem, &protocol->session_manager, mount_point);
// cleanup on error
if (!success)
{
wf_impl_jsonrpc_server_cleanup(&protocol->server);
wf_impl_authenticators_cleanup(&protocol->authenticators);
wf_impl_timeout_manager_cleanup(&protocol->timeout_manager);
wf_impl_session_manager_cleanup(&protocol->session_manager);
}
return success;
wf_impl_jsonrpc_server_add(&protocol->server, "add_filesystem", &wf_impl_server_protocol_add_filesystem, protocol);
}
void wf_impl_server_protocol_cleanup(
struct wf_server_protocol * protocol)
{
wf_impl_filesystem_cleanup(&protocol->filesystem);
free(protocol->mount_point);
wf_impl_jsonrpc_server_cleanup(&protocol->server);
wf_impl_timeout_manager_cleanup(&protocol->timeout_manager);
wf_impl_authenticators_cleanup(&protocol->authenticators);

View File

@@ -1,7 +1,6 @@
#ifndef WF_ADAPTER_IMPL_SERVER_PROTOCOL_H
#define WF_ADAPTER_IMPL_SERVER_PROTOCOL_H
#include "webfuse/adapter/impl/filesystem.h"
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/adapter/impl/time/timeout_manager.h"
#include "webfuse/adapter/impl/authenticators.h"
@@ -17,14 +16,14 @@ struct lws_protocols;
struct wf_server_protocol
{
char * mount_point;
struct wf_impl_timeout_manager timeout_manager;
struct wf_impl_filesystem filesystem;
struct wf_impl_authenticators authenticators;
struct wf_impl_session_manager session_manager;
struct wf_impl_jsonrpc_server server;
};
extern bool wf_impl_server_protocol_init(
extern void wf_impl_server_protocol_init(
struct wf_server_protocol * protocol,
char * mount_point);

View File

@@ -6,8 +6,12 @@
#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 <libwebsockets.h>
#include <stddef.h>
#include <stdlib.h>
static bool wf_impl_session_send(
json_t * request,
@@ -20,7 +24,7 @@ static bool wf_impl_session_send(
if (result)
{
wf_message_queue_push(&session->queue, message);
wf_slist_append(&session->messages, &message->item);
lws_callback_on_writable(session->wsi);
result = true;
@@ -33,31 +37,59 @@ static bool wf_impl_session_send(
return result;
}
void wf_impl_session_init(
struct wf_impl_session * session,
struct wf_impl_session * wf_impl_session_create(
struct lws * wsi,
struct wf_impl_authenticators * authenticators,
struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server)
{
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);
}
struct wf_impl_jsonrpc_server * server,
char const * mount_point)
{
void wf_impl_session_cleanup(
struct wf_impl_session * session = malloc(sizeof(struct wf_impl_session));
if (NULL != session)
{
wf_slist_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_slist_init(&session->messages);
}
return session;
}
static void wf_impl_session_dispose_filesystems(
struct wf_slist * filesystems)
{
struct wf_slist_item * item = filesystems->first;
while (NULL != item)
{
struct wf_slist_item * next = item->next;
struct wf_impl_filesystem * filesystem = WF_CONTAINER_OF(item, struct wf_impl_filesystem, item);
wf_impl_filesystem_dispose(filesystem);
item = next;
}
}
void wf_impl_session_dispose(
struct wf_impl_session * session)
{
wf_impl_session_dispose_filesystems(&session->filesystems);
wf_impl_jsonrpc_proxy_cleanup(&session->rpc);
wf_message_queue_cleanup(&session->queue);
wf_message_queue_cleanup(&session->messages);
session->is_authenticated = false;
session->wsi = NULL;
session->authenticators = NULL;
session->server = NULL;
}
free(session->mount_point);
free(session);
}
bool wf_impl_session_authenticate(
struct wf_impl_session * session,
@@ -68,16 +100,27 @@ bool wf_impl_session_authenticate(
return session->is_authenticated;
}
bool wf_impl_session_add_filesystem(
struct wf_impl_session * session,
char const * name)
{
struct wf_impl_filesystem * filesystem = wf_impl_filesystem_create(session, name);
wf_slist_append(&session->filesystems, &filesystem->item);
return (NULL != filesystem);
}
void wf_impl_session_onwritable(
struct wf_impl_session * session)
{
if (!wf_message_queue_empty(&session->queue))
{
struct wf_message * message = wf_message_queue_pop(&session->queue);
if (!wf_slist_empty(&session->messages))
{
struct wf_slist_item * item = wf_slist_remove_first(&session->messages);
struct wf_message * message = WF_CONTAINER_OF(item, struct wf_message, item);
lws_write(session->wsi, (unsigned char*) message->data, message->length, LWS_WRITE_TEXT);
wf_message_dispose(message);
if (!wf_message_queue_empty(&session->queue))
if (!wf_slist_empty(&session->messages))
{
lws_callback_on_writable(session->wsi);
}
@@ -105,4 +148,48 @@ void wf_impl_session_receive(
json_decref(message);
}
}
}
static struct wf_impl_filesystem * wf_impl_session_get_filesystem(
struct wf_impl_session * session,
struct lws * wsi)
{
struct wf_impl_filesystem * result = NULL;
struct wf_slist_item * item = session->filesystems.first;
while (NULL != item)
{
struct wf_slist_item * next = item->next;
struct wf_impl_filesystem * filesystem = WF_CONTAINER_OF(session->filesystems.first, struct wf_impl_filesystem, item);
if (wsi == filesystem->wsi)
{
result = filesystem;
break;
}
item = next;
}
return result;
}
bool wf_impl_session_contains_wsi(
struct wf_impl_session * session,
struct lws * wsi)
{
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

@@ -12,6 +12,8 @@ using std::size_t;
#include "webfuse/core/message_queue.h"
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/adapter/impl/jsonrpc/server.h"
#include "webfuse/adapter/impl/filesystem.h"
#include "webfuse/core/slist.h"
#ifdef __cplusplus
extern "C"
@@ -26,25 +28,35 @@ struct wf_impl_timeout_manager;
struct wf_impl_session
{
struct wf_slist_item item;
char * mount_point;
struct lws * wsi;
bool is_authenticated;
struct wf_message_queue queue;
struct wf_slist messages;
struct wf_impl_authenticators * authenticators;
struct wf_impl_jsonrpc_server * server;
struct wf_impl_jsonrpc_proxy rpc;
struct wf_slist filesystems;
};
extern void wf_impl_session_init(
struct wf_impl_session * session,
extern struct wf_impl_session * wf_impl_session_create(
struct lws * wsi,
struct wf_impl_authenticators * authenticators,
struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server);
struct wf_impl_authenticators * authenticators,
struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server,
char const * mount_point);
extern void wf_impl_session_dispose(
struct wf_impl_session * session);
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,
@@ -53,8 +65,14 @@ extern void wf_impl_session_receive(
extern void wf_impl_session_onwritable(
struct wf_impl_session * session);
extern void wf_impl_session_cleanup(
struct wf_impl_session * session);
extern bool wf_impl_session_contains_wsi(
struct wf_impl_session * session,
struct lws * wsi);
extern void wf_impl_session_process_filesystem_request(
struct wf_impl_session * session,
struct lws * wsi);
#ifdef __cplusplus
}

View File

@@ -1,17 +1,26 @@
#include "webfuse/adapter/impl/session_manager.h"
#include "webfuse/core/util.h"
#include "webfuse/core/container_of.h"
#include <stddef.h>
void wf_impl_session_manager_init(
struct wf_impl_session_manager * manager)
{
wf_impl_session_init(&manager->session, NULL, NULL, NULL, NULL);
wf_slist_init(&manager->sessions);
}
void wf_impl_session_manager_cleanup(
struct wf_impl_session_manager * manager)
{
wf_impl_session_cleanup(&manager->session);
struct wf_slist_item * item = manager->sessions.first;
while (NULL != item)
{
struct wf_slist_item * next = item->next;
struct wf_impl_session * session = WF_CONTAINER_OF(item, struct wf_impl_session, item);
wf_impl_session_dispose(session);
item = next;
}
}
struct wf_impl_session * wf_impl_session_manager_add(
@@ -19,13 +28,14 @@ struct wf_impl_session * wf_impl_session_manager_add(
struct lws * wsi,
struct wf_impl_authenticators * authenticators,
struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server)
struct wf_impl_jsonrpc_server * server,
char const * mount_point)
{
struct wf_impl_session * session = NULL;
if (NULL == manager->session.wsi)
struct wf_impl_session * session = wf_impl_session_create(
wsi, authenticators, timeout_manager, server, mount_point);
if (NULL != session)
{
session = &manager->session;
wf_impl_session_init(&manager->session, wsi, authenticators, timeout_manager, server);
wf_slist_append(&manager->sessions, &session->item);
}
return session;
@@ -36,37 +46,42 @@ struct wf_impl_session * wf_impl_session_manager_get(
struct lws * wsi)
{
struct wf_impl_session * session = NULL;
if (wsi == manager->session.wsi)
struct wf_slist_item * item = manager->sessions.first;
while (NULL != item)
{
session = &manager->session;
struct wf_slist_item * next = item->next;
struct wf_impl_session * current = WF_CONTAINER_OF(item, struct wf_impl_session, item);
if (wf_impl_session_contains_wsi(current, wsi)) {
session = current;
break;
}
item = next;
}
return session;
}
struct wf_impl_session * wf_impl_session_manager_get_by_inode(
struct wf_impl_session_manager * manager,
fuse_ino_t WF_UNUSED_PARAM(inode))
{
// ToDo: use inode to determine session manager
struct wf_impl_session * session = NULL;
if (NULL != manager->session.wsi)
{
session = &manager->session;
}
return session;
}
void wf_impl_session_manager_remove(
struct wf_impl_session_manager * manager,
struct lws * wsi)
{
if (wsi == manager->session.wsi)
struct wf_slist_item * item = manager->sessions.first;
struct wf_slist_item * prev = NULL;
while (NULL != item)
{
wf_impl_session_cleanup(&manager->session);
manager->session.wsi = NULL;
struct wf_slist_item * next = item->next;
struct wf_impl_session * session = WF_CONTAINER_OF(item, struct wf_impl_session, item);
if (wsi == session->wsi)
{
wf_slist_remove_after(&manager->sessions, prev);
wf_impl_session_dispose(session);
break;
}
prev = item;
item = next;
}
}

View File

@@ -7,6 +7,7 @@
#include "webfuse/adapter/impl/session.h"
#include "webfuse/adapter/impl/fuse_wrapper.h"
#include "webfuse/core/slist.h"
#ifdef __cplusplus
extern "C"
@@ -19,7 +20,7 @@ struct wf_impl_jsonrpc_server;
struct wf_impl_session_manager
{
struct wf_impl_session session;
struct wf_slist sessions;
};
extern void wf_impl_session_manager_init(
@@ -33,16 +34,13 @@ extern struct wf_impl_session * wf_impl_session_manager_add(
struct lws * wsi,
struct wf_impl_authenticators * authenticators,
struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server);
struct wf_impl_jsonrpc_server * server,
char const * mount_point);
extern struct wf_impl_session * wf_impl_session_manager_get(
struct wf_impl_session_manager * manager,
struct lws * wsi);
extern struct wf_impl_session * wf_impl_session_manager_get_by_inode(
struct wf_impl_session_manager * session_manger,
fuse_ino_t inode);
extern void wf_impl_session_manager_remove(
struct wf_impl_session_manager * manager,
struct lws * wsi);

View File

@@ -0,0 +1,13 @@
#ifndef WF_CONTAINER_OF_H
#define WF_CONTAINER_OF_H
#ifndef __cplusplus
#include <stddef.h>
#else
#include <cstddef>
#endif
#define WF_CONTAINER_OF(pointer, type, member) \
(type *) (((char *) pointer) - offsetof(type, member))
#endif

View File

@@ -16,7 +16,6 @@ extern struct wf_message * wf_message_create(json_t const * value)
{
message->data = &data[sizeof(struct wf_message) + LWS_PRE];
message->length = length;
message->next = NULL;
json_dumpb(value, message->data, length, JSON_COMPACT);
}

View File

@@ -9,10 +9,11 @@ using std::size_t;
#endif
#include <jansson.h>
#include "webfuse/core/slist.h"
struct wf_message
{
struct wf_message * next;
struct wf_slist_item item;
char * data;
size_t length;
};
@@ -22,7 +23,8 @@ extern "C"
{
#endif
extern struct wf_message * wf_message_create(json_t const * value);
extern struct wf_message * wf_message_create(
json_t const * value);
extern void wf_message_dispose(
struct wf_message * message);

View File

@@ -1,63 +1,17 @@
#include "webfuse/core/message_queue.h"
#include "webfuse/core/message.h"
void wf_message_queue_init(
struct wf_message_queue * queue)
{
queue->first = NULL;
queue->last = NULL;
}
#include "webfuse/core/container_of.h"
void wf_message_queue_cleanup(
struct wf_message_queue * queue)
struct wf_slist * queue)
{
struct wf_message * message = queue->first;
while (NULL != message)
struct wf_slist_item * item = queue->first;
while (NULL != item)
{
struct wf_message * next = message->next;
struct wf_slist_item * next = item->next;
struct wf_message * message = WF_CONTAINER_OF(item, struct wf_message, item);
wf_message_dispose(message);
message = next;
item = next;
}
wf_message_queue_init(queue);
}
bool wf_message_queue_empty(
struct wf_message_queue * queue)
{
return (NULL == queue->first);
}
void wf_message_queue_push(
struct wf_message_queue * queue,
struct wf_message * message)
{
message->next = NULL;
if (NULL != queue->last)
{
queue->last->next = message;
queue->last = message;
}
else
{
queue->first = message;
queue->last = message;
}
}
struct wf_message * wf_message_queue_pop(
struct wf_message_queue * queue)
{
struct wf_message * const result = queue->first;
if (NULL != result)
{
queue->first = queue->first->next;
if (NULL == queue->first)
{
queue->last = NULL;
}
}
return result;
wf_slist_init(queue);
}

View File

@@ -1,39 +1,16 @@
#ifndef WF_MESSAGE_QUEUE_H
#define WF_MESSAGE_QUEUE_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
struct wf_message_queue;
struct wf_message;
struct wf_message_queue
{
struct wf_message * first;
struct wf_message * last;
};
#ifdef __cplusplus
extern "C"
{
#endif
extern void wf_message_queue_init(
struct wf_message_queue * queue);
struct wf_slist;
extern void wf_message_queue_cleanup(
struct wf_message_queue * queue);
struct wf_slist * queue);
extern bool wf_message_queue_empty(
struct wf_message_queue * queue);
extern void wf_message_queue_push(
struct wf_message_queue * queue,
struct wf_message * message);
extern struct wf_message * wf_message_queue_pop(
struct wf_message_queue * queue);
#ifdef __cplusplus
}

77
lib/webfuse/core/slist.c Normal file
View File

@@ -0,0 +1,77 @@
#include "webfuse/core/slist.h"
#include <stddef.h>
void wf_slist_init(
struct wf_slist * list)
{
list->first = NULL;
list->last = NULL;
}
bool wf_slist_empty(
struct wf_slist * list)
{
return (NULL == list->first);
}
void wf_slist_append(
struct wf_slist * list,
struct wf_slist_item * item)
{
item->next = NULL;
if (NULL != list->last)
{
list->last->next = item;
list->last = item;
}
else
{
list->first = item;
list->last = item;
}
}
struct wf_slist_item * wf_slist_remove_first(
struct wf_slist * list)
{
struct wf_slist_item * const result = list->first;
if (NULL != result)
{
list->first = list->first->next;
if (NULL == list->first)
{
list->last = NULL;
}
}
return result;
}
struct wf_slist_item * wf_slist_remove_after(
struct wf_slist * list,
struct wf_slist_item * prev)
{
struct wf_slist_item * result = NULL;
if (NULL != prev)
{
result = prev->next;
if ((NULL != result) && (NULL != result->next))
{
prev->next = result->next;
}
else
{
list->last = prev;
prev->next = NULL;
}
}
else
{
result = wf_slist_remove_first(list);
}
return result;
}

45
lib/webfuse/core/slist.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef WF_SLIST_H
#define WF_SLIST_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
struct wf_slist_item
{
struct wf_slist_item * next;
};
struct wf_slist
{
struct wf_slist_item * first;
struct wf_slist_item * last;
};
extern void wf_slist_init(
struct wf_slist * list);
extern bool wf_slist_empty(
struct wf_slist * list);
extern void wf_slist_append(
struct wf_slist * list,
struct wf_slist_item * item);
extern struct wf_slist_item * wf_slist_remove_first(
struct wf_slist * list);
extern struct wf_slist_item * wf_slist_remove_after(
struct wf_slist * list,
struct wf_slist_item * prev);
#ifdef __cplusplus
}
#endif
#endif

35
lib/webfuse/core/string.c Normal file
View File

@@ -0,0 +1,35 @@
#include "webfuse/core/string.h"
#include <stdio.h>
#include <stdlib.h>
char * wf_create_string(char const * format, ...)
{
char * result = NULL;
va_list measure_args;
va_start(measure_args, format);
char buffer;
int needed = vsnprintf(&buffer, 1, format, measure_args); /* Flawfinder: ignore */
va_end(measure_args);
if (0 <= needed)
{
result = malloc(needed + 1);
if (NULL != result)
{
va_list args;
va_start(args, format);
int count = vsnprintf(result, needed + 1, format, args); /* Flawfinder: ignore */
va_end(args);
if ((count < 0) || (needed < count))
{
free(result);
result = NULL;
}
}
}
return result;
}

21
lib/webfuse/core/string.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef WF_CORE_STRING_H
#define WF_CORE_STRING_H
#ifndef __cplusplus
#include <stdarg.h>
#else
#include <cstdarg>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
extern char * wf_create_string(char const * format, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -10,6 +10,8 @@
#include "webfuse/provider/impl/provider.h"
#include "webfuse/core/util.h"
#include "webfuse/core/message.h"
#include "webfuse/core/message_queue.h"
#include "webfuse/core/container_of.h"
static void wfp_impl_client_protocol_respond(
json_t * response,
@@ -20,7 +22,7 @@ static void wfp_impl_client_protocol_respond(
struct wf_message * message = wf_message_create(response);
if (NULL != message)
{
wf_message_queue_push(&protocol->queue, message);
wf_slist_append(&protocol->messages, &message->item);
lws_callback_on_writable(protocol->wsi);
}
}
@@ -45,6 +47,26 @@ static void wfp_impl_client_protocol_process_request(
}
}
static void wfp_impl_client_protocol_add_filesystem(
struct wfp_client_protocol * protocol)
{
json_t * params = json_array();
json_array_append_new(params, json_string("cprovider"));
json_t * request = json_object();
json_object_set_new(request, "method", json_string("add_filesystem"));
json_object_set_new(request, "params", params);
json_object_set_new(request, "id", json_integer(42));
struct wf_message * message = wf_message_create(request);
if (NULL != message)
{
wf_slist_append(&protocol->messages, &message->item);
lws_callback_on_writable(protocol->wsi);
}
json_decref(request);
}
static int wfp_impl_client_protocol_callback(
struct lws * wsi,
@@ -61,6 +83,7 @@ static int wfp_impl_client_protocol_callback(
switch (reason)
{
case LWS_CALLBACK_CLIENT_ESTABLISHED:
wfp_impl_client_protocol_add_filesystem(protocol);
protocol->provider.connected(protocol->user_data);
break;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
@@ -75,13 +98,14 @@ static int wfp_impl_client_protocol_callback(
case LWS_CALLBACK_SERVER_WRITEABLE:
// fall-through
case LWS_CALLBACK_CLIENT_WRITEABLE:
if ((wsi == protocol->wsi) && (!wf_message_queue_empty(&protocol->queue)))
if ((wsi == protocol->wsi) && (!wf_slist_empty(&protocol->messages)))
{
struct wf_message * message = wf_message_queue_pop(&protocol->queue);
struct wf_slist_item * item = wf_slist_remove_first(&protocol->messages);
struct wf_message * message = WF_CONTAINER_OF(item, struct wf_message, item);
lws_write(wsi, (unsigned char*) message->data, message->length, LWS_WRITE_TEXT);
wf_message_dispose(message);
if (!wf_message_queue_empty(&protocol->queue))
if (!wf_slist_empty(&protocol->messages))
{
lws_callback_on_writable(wsi);
@@ -102,7 +126,7 @@ void wfp_impl_client_protocol_init(
struct wfp_provider const * provider,
void * user_data)
{
wf_message_queue_init(&protocol->queue);
wf_slist_init(&protocol->messages);
protocol->wsi = NULL;
@@ -116,7 +140,7 @@ void wfp_impl_client_protocol_init(
void wfp_impl_client_protocol_cleanup(
struct wfp_client_protocol * protocol)
{
wf_message_queue_cleanup(&protocol->queue);
wf_message_queue_cleanup(&protocol->messages);
}
struct wfp_client_protocol * wfp_impl_client_protocol_create(

View File

@@ -4,7 +4,7 @@
#include "webfuse/provider/impl/provider.h"
#include "webfuse/provider/impl/request.h"
#include "webfuse/core/message_queue.h"
#include "webfuse/core/slist.h"
#ifdef __cplusplus
extern "C"
@@ -20,7 +20,7 @@ struct wfp_client_protocol
struct wfp_provider provider;
void * user_data;
struct lws * wsi;
struct wf_message_queue queue;
struct wf_slist messages;
};
extern void wfp_impl_client_protocol_init(

View File

@@ -8,11 +8,11 @@ void wfp_impl_close(
int WF_UNUSED_PARAM(id))
{
size_t const param_count = json_array_size(params);
if (3 == param_count)
if (4 == param_count)
{
json_t * inode_holder = json_array_get(params, 0);
json_t * handle_holder = json_array_get(params, 1);
json_t * flags_holder = json_array_get(params, 2);
json_t * inode_holder = json_array_get(params, 1);
json_t * handle_holder = json_array_get(params, 2);
json_t * flags_holder = json_array_get(params, 3);
if (json_is_integer(inode_holder) &&
json_is_integer(handle_holder) &&

View File

@@ -13,9 +13,9 @@ void wfp_impl_getattr(
int id)
{
size_t const count = json_array_size(params);
if (1 == count)
if (2 == count)
{
json_t * inode_holder = json_array_get(params, 0);
json_t * inode_holder = json_array_get(params, 1);
if (json_is_integer(inode_holder))
{

View File

@@ -12,10 +12,10 @@ void wfp_impl_lookup(
int id)
{
size_t const count = json_array_size(params);
if (2 == count)
if (3 == count)
{
json_t * inode_holder = json_array_get(params, 0);
json_t * name_holder = json_array_get(params, 1);
json_t * inode_holder = json_array_get(params, 1);
json_t * name_holder = json_array_get(params, 2);
if (json_is_integer(inode_holder) &&
json_is_string(name_holder))

View File

@@ -9,10 +9,10 @@ void wfp_impl_open(
int id)
{
size_t const count = json_array_size(params);
if (2 == count)
if (3 == count)
{
json_t * inode_holder = json_array_get(params, 0);
json_t * flags_holder = json_array_get(params, 1);
json_t * inode_holder = json_array_get(params, 1);
json_t * flags_holder = json_array_get(params, 2);
if (json_is_integer(inode_holder) &&
json_is_integer(flags_holder))

View File

@@ -13,12 +13,12 @@ void wfp_impl_read(
int id)
{
size_t const count = json_array_size(params);
if (4 == count)
if (5 == count)
{
json_t * inode_holder = json_array_get(params, 0);
json_t * handle_holder = json_array_get(params, 1);
json_t * offset_holder = json_array_get(params, 2);
json_t * length_holder = json_array_get(params, 3);
json_t * inode_holder = json_array_get(params, 1);
json_t * handle_holder = json_array_get(params, 2);
json_t * offset_holder = json_array_get(params, 3);
json_t * length_holder = json_array_get(params, 4);
if (json_is_integer(inode_holder) &&
json_is_integer(handle_holder) &&

View File

@@ -10,9 +10,9 @@ void wfp_impl_readdir(
int id)
{
size_t const count = json_array_size(params);
if (1 == count)
if (2 == count)
{
json_t * inode_holder = json_array_get(params, 0);
json_t * inode_holder = json_array_get(params, 1);
if ((NULL != inode_holder) && (json_is_integer(inode_holder)))
{