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:
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user