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);
|
||||
|
||||
13
lib/webfuse/core/container_of.h
Normal file
13
lib/webfuse/core/container_of.h
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
77
lib/webfuse/core/slist.c
Normal 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
45
lib/webfuse/core/slist.h
Normal 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
35
lib/webfuse/core/string.c
Normal 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
21
lib/webfuse/core/string.h
Normal 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
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
@@ -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)))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user