mirror of
https://github.com/falk-werner/webfuse-provider
synced 2024-10-27 20:44:10 +00:00
fixed unit tests; added logging support; allow to specify filesystem name
This commit is contained in:
parent
8140afe2ab
commit
c26342cefd
@ -16,6 +16,7 @@ struct config
|
||||
char * url;
|
||||
struct wfp_client_config * client_config;
|
||||
bool show_help;
|
||||
bool is_verbose;
|
||||
};
|
||||
|
||||
enum fs_entry_type
|
||||
@ -37,6 +38,8 @@ struct fs_entry
|
||||
|
||||
struct fs
|
||||
{
|
||||
bool is_verbose;
|
||||
bool connection_closed;
|
||||
struct fs_entry const * entries;
|
||||
};
|
||||
|
||||
@ -49,10 +52,12 @@ static void show_help()
|
||||
"Usage: webfuse-provider -u <url> [-k <key_path>] [-c <cert_path>]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
"\t-u, --url URL of webfuse server (required)\n"
|
||||
"\t-k, --key_path Path to private key of provider (default: not set, TLS disabled)\n"
|
||||
"\t-c, --cert_path Path to certificate of provider (defautl: not set, TLS disabled)\n"
|
||||
"\t-h, --help prints this message\n"
|
||||
"\t-u, --url URL of webfuse server (required)\n"
|
||||
"\t-k, --key_path Path to private key of provider (default: not set, TLS disabled)\n"
|
||||
"\t-c, --cert_path Path to certificate of provider (defautl: not set, TLS disabled)\n"
|
||||
"\t-n, --filesystem_name Name of the filesystem (default: \"cprovider\")\n"
|
||||
"\t-v, --verbose print additional log messages\n"
|
||||
"\t-h, --help prints this message\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
"\twebfuse-provider -u ws://localhost:8080/\n"
|
||||
@ -70,16 +75,20 @@ static int parse_arguments(
|
||||
{"url", required_argument, NULL, 'u'},
|
||||
{"key_path", required_argument, NULL, 'k'},
|
||||
{"cert_path", required_argument, NULL, 'c'},
|
||||
{"filesystem_name", required_argument, NULL, 'n'},
|
||||
{"verbose", required_argument, NULL, 'v'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
int result = EXIT_SUCCESS;
|
||||
bool finished = false;
|
||||
while (!finished)
|
||||
{
|
||||
int option_index = 0;
|
||||
int const c = getopt_long(argc, argv, "u:k:c:h", options, &option_index);
|
||||
int const c = getopt_long(argc, argv, "u:k:c:n:vh", options, &option_index);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
@ -100,6 +109,12 @@ static int parse_arguments(
|
||||
case 'c':
|
||||
wfp_client_config_set_certpath(config->client_config, optarg);
|
||||
break;
|
||||
case 'n':
|
||||
wfp_client_config_set_fsname(config->client_config, optarg);
|
||||
break;
|
||||
case 'v':
|
||||
config->is_verbose = true;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "error: unknown argument\n");
|
||||
finished = true;
|
||||
@ -133,7 +148,7 @@ static struct fs_entry const * fs_getentry(
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -269,7 +284,7 @@ static void fs_open(
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WFP_BAD_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -306,7 +321,7 @@ static void fs_read(
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WFP_BAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -322,11 +337,43 @@ static void on_interrupt(int signal_id)
|
||||
shutdown_requested = true;
|
||||
}
|
||||
|
||||
static void on_connected(void* user_data)
|
||||
{
|
||||
struct fs * fs = user_data;
|
||||
if (fs->is_verbose) { puts("connected"); }
|
||||
}
|
||||
|
||||
static void on_disconnected(void* user_data)
|
||||
{
|
||||
struct fs * fs = user_data;
|
||||
if (fs->is_verbose) { puts("disconnected"); }
|
||||
fs->connection_closed = true;
|
||||
}
|
||||
|
||||
static void do_log(
|
||||
void * user_data,
|
||||
int level,
|
||||
char const * format,
|
||||
...)
|
||||
{
|
||||
struct fs * fs = user_data;
|
||||
if (fs->is_verbose)
|
||||
{
|
||||
printf("LOG: ");
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
puts("");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
struct config config;
|
||||
config.url = NULL;
|
||||
config.show_help = false;
|
||||
config.is_verbose = false;
|
||||
config.client_config = wfp_client_config_create();
|
||||
int result = parse_arguments(argc, argv, &config);
|
||||
|
||||
@ -349,6 +396,8 @@ int main(int argc, char* argv[])
|
||||
|
||||
struct fs fs =
|
||||
{
|
||||
.is_verbose = config.is_verbose,
|
||||
.connection_closed = false,
|
||||
.entries = entries
|
||||
};
|
||||
|
||||
@ -360,17 +409,20 @@ int main(int argc, char* argv[])
|
||||
wfp_client_config_set_onreaddir(config.client_config, &fs_readdir);
|
||||
wfp_client_config_set_onopen(config.client_config, &fs_open);
|
||||
wfp_client_config_set_onread(config.client_config, &fs_read);
|
||||
wfp_client_config_set_onconnected(config.client_config, &on_connected);
|
||||
wfp_client_config_set_ondisconnected(config.client_config, &on_disconnected);
|
||||
wfp_client_config_set_logger(config.client_config, &do_log);
|
||||
|
||||
struct wfp_client * client = wfp_client_create(config.client_config);
|
||||
wfp_client_connect(client, config.url);
|
||||
|
||||
while (!shutdown_requested)
|
||||
while ((!shutdown_requested) && (!fs.connection_closed))
|
||||
{
|
||||
wfp_client_service(client);
|
||||
}
|
||||
|
||||
wfp_client_dispose(client);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.show_help)
|
||||
{
|
||||
@ -380,4 +432,4 @@ int main(int argc, char* argv[])
|
||||
free(config.url);
|
||||
wfp_client_config_dispose(config.client_config);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,12 @@
|
||||
#include <webfuse_provider/operation/read.h>
|
||||
#include <webfuse_provider/credentials.h>
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <cstdarg>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
@ -45,6 +51,20 @@ typedef void wfp_connected_fn(
|
||||
typedef void wfp_disconnected_fn(
|
||||
void * user_data);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Callback to log
|
||||
///
|
||||
/// \param user data user defined context
|
||||
/// \param level log level
|
||||
/// \param format format string (see printf)
|
||||
/// \param ... arguments
|
||||
//------------------------------------------------------------------------------
|
||||
typedef void wfp_log_fn(
|
||||
void * user_data,
|
||||
int level,
|
||||
char const * format,
|
||||
...);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Creates a new client configuration.
|
||||
///
|
||||
@ -225,13 +245,33 @@ extern WFP_API void wfp_client_config_set_onread(
|
||||
/// \brief Enabled authentication.
|
||||
///
|
||||
/// \param config pointer to client configuration
|
||||
/// \param get_credentials pointer to function providing credentials when
|
||||
/// \param get_credentials pointer to function providing credentials when
|
||||
// needed.
|
||||
//------------------------------------------------------------------------------
|
||||
extern WFP_API void wfp_client_config_enable_authentication(
|
||||
struct wfp_client_config * config,
|
||||
wfp_get_credentials_fn * get_credentials);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Set filesystem name.
|
||||
///
|
||||
/// \param config pointer to client configuration
|
||||
/// \param name Name of the filesystem ("cprovider" will be used if unset)
|
||||
//------------------------------------------------------------------------------
|
||||
extern WFP_API void wfp_client_config_set_fsname(
|
||||
struct wfp_client_config * config,
|
||||
char const * name);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Set logger function.
|
||||
///
|
||||
/// \param config pointer to client configuration
|
||||
/// \param log logger function
|
||||
//------------------------------------------------------------------------------
|
||||
extern WFP_API void wfp_client_config_set_logger(
|
||||
struct wfp_client_config * config,
|
||||
wfp_log_fn * log);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -165,6 +165,20 @@ void wfp_client_config_enable_authentication(
|
||||
wfp_impl_client_config_enable_authentication(config, get_credentials);
|
||||
}
|
||||
|
||||
void wfp_client_config_set_fsname(
|
||||
struct wfp_client_config * config,
|
||||
char const * name)
|
||||
{
|
||||
wfp_impl_client_config_set_fsname(config, name);
|
||||
}
|
||||
|
||||
void wfp_client_config_set_logger(
|
||||
struct wfp_client_config * config,
|
||||
wfp_log_fn * log)
|
||||
{
|
||||
wfp_impl_client_config_set_logger(config, log);
|
||||
}
|
||||
|
||||
// protocol
|
||||
|
||||
|
||||
|
@ -28,9 +28,9 @@ struct wfp_client * wfp_impl_client_create(
|
||||
struct wfp_client_config * config)
|
||||
{
|
||||
wfp_impl_lwslog_disable();
|
||||
|
||||
|
||||
struct wfp_client * client = malloc(sizeof(struct wfp_client));
|
||||
wfp_impl_client_protocol_init(&client->protocol, &config->provider, config->user_data);
|
||||
wfp_impl_client_protocol_init(&client->protocol, &config->provider, config->fs_name, config->user_data);
|
||||
|
||||
memset(client->protocols, 0, sizeof(struct lws_protocols) * WFP_CLIENT_PROTOCOL_COUNT);
|
||||
wfp_impl_client_protocol_init_lws(&client->protocol, &client->protocols[0]);
|
||||
@ -65,7 +65,7 @@ void wfp_impl_client_dispose(
|
||||
struct wfp_client * client)
|
||||
{
|
||||
lws_context_destroy(client->context);
|
||||
wfp_impl_client_protocol_cleanup(&client->protocol);
|
||||
wfp_impl_client_protocol_cleanup(&client->protocol);
|
||||
free(client);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ struct wfp_client_config * wfp_impl_client_config_create(void)
|
||||
config->key_path = NULL;
|
||||
config->cert_path = NULL;
|
||||
config->ca_filepath = NULL;
|
||||
config->fs_name = strdup("cprovider");
|
||||
|
||||
return config;
|
||||
}
|
||||
@ -18,6 +19,7 @@ struct wfp_client_config * wfp_impl_client_config_create(void)
|
||||
void wfp_impl_client_config_dispose(
|
||||
struct wfp_client_config * config)
|
||||
{
|
||||
free(config->fs_name);
|
||||
free(config->key_path);
|
||||
free(config->cert_path);
|
||||
free(config->ca_filepath);
|
||||
@ -52,7 +54,7 @@ void wfp_impl_client_config_set_ca_filepath(
|
||||
char const * ca_filepath)
|
||||
{
|
||||
free(config->ca_filepath);
|
||||
config->ca_filepath = strdup(ca_filepath);
|
||||
config->ca_filepath = strdup(ca_filepath);
|
||||
}
|
||||
|
||||
void wfp_impl_client_config_set_onconnected(
|
||||
@ -117,3 +119,18 @@ void wfp_impl_client_config_enable_authentication(
|
||||
{
|
||||
config->provider.get_credentials = get_credentials;
|
||||
}
|
||||
|
||||
void wfp_impl_client_config_set_fsname(
|
||||
struct wfp_client_config * config,
|
||||
char const * name)
|
||||
{
|
||||
free(config->fs_name);
|
||||
config->fs_name = strdup(name);
|
||||
}
|
||||
|
||||
void wfp_impl_client_config_set_logger(
|
||||
struct wfp_client_config * config,
|
||||
wfp_log_fn * log)
|
||||
{
|
||||
config->provider.log = log;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ struct wfp_client_config
|
||||
char * key_path;
|
||||
char * cert_path;
|
||||
char * ca_filepath;
|
||||
char * fs_name;
|
||||
};
|
||||
|
||||
extern struct wfp_client_config * wfp_impl_client_config_create(void);
|
||||
@ -75,6 +76,14 @@ extern void wfp_impl_client_config_enable_authentication(
|
||||
struct wfp_client_config * config,
|
||||
wfp_get_credentials_fn * get_credentials);
|
||||
|
||||
extern void wfp_impl_client_config_set_fsname(
|
||||
struct wfp_client_config * config,
|
||||
char const * name);
|
||||
|
||||
extern void wfp_impl_client_config_set_logger(
|
||||
struct wfp_client_config * config,
|
||||
wfp_log_fn * log);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -35,7 +35,7 @@ static void wfp_impl_client_protocol_respond(
|
||||
}
|
||||
|
||||
static void wfp_impl_client_protocol_process(
|
||||
struct wfp_client_protocol * protocol,
|
||||
struct wfp_client_protocol * protocol,
|
||||
char * data,
|
||||
size_t length)
|
||||
{
|
||||
@ -64,62 +64,71 @@ static void wfp_impl_client_protocol_process(
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static void
|
||||
wfp_impl_client_protocol_on_add_filesystem_finished(
|
||||
void * user_data,
|
||||
struct wfp_json const * result,
|
||||
struct wfp_jsonrpc_error const * WFP_UNUSED_PARAM(error))
|
||||
struct wfp_jsonrpc_error const * WFP_UNUSED_PARAM(error))
|
||||
{
|
||||
struct wfp_client_protocol * protocol = user_data;
|
||||
if (NULL == protocol->wsi) { return; }
|
||||
|
||||
if (NULL != result)
|
||||
{
|
||||
protocol->provider.log(protocol->user_data, 0, "filesystem added");
|
||||
protocol->provider.log(protocol->user_data, 0, "handshake finished");
|
||||
protocol->is_connected = true;
|
||||
protocol->provider.connected(protocol->user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
protocol->provider.log(protocol->user_data, 0, "add filesystem failed");
|
||||
protocol->is_shutdown_requested = true;
|
||||
lws_callback_on_writable(protocol->wsi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wfp_impl_client_protocol_add_filesystem(
|
||||
struct wfp_client_protocol * protocol)
|
||||
{
|
||||
protocol->provider.log(protocol->user_data, 0, "begin add filesystem");
|
||||
|
||||
wfp_jsonrpc_proxy_invoke(
|
||||
protocol->proxy,
|
||||
protocol->proxy,
|
||||
&wfp_impl_client_protocol_on_add_filesystem_finished,
|
||||
protocol,
|
||||
"add_filesystem",
|
||||
"s",
|
||||
"cprovider");
|
||||
protocol->fs_name);
|
||||
}
|
||||
|
||||
static void
|
||||
static void
|
||||
wfp_impl_client_protocol_on_authenticate_finished(
|
||||
void * user_data,
|
||||
struct wfp_json const * result,
|
||||
struct wfp_jsonrpc_error const * WFP_UNUSED_PARAM(error))
|
||||
struct wfp_jsonrpc_error const * WFP_UNUSED_PARAM(error))
|
||||
{
|
||||
struct wfp_client_protocol * protocol = user_data;
|
||||
if (NULL == protocol->wsi) { return; }
|
||||
|
||||
if (NULL != result)
|
||||
{
|
||||
protocol->provider.log(protocol->user_data, 0, "authentication finished");
|
||||
wfp_impl_client_protocol_add_filesystem(protocol);
|
||||
}
|
||||
else
|
||||
{
|
||||
protocol->provider.log(protocol->user_data, 0, "authentication failed");
|
||||
protocol->is_shutdown_requested = true;
|
||||
lws_callback_on_writable(protocol->wsi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wfp_impl_client_protocol_authenticate(
|
||||
struct wfp_client_protocol * protocol)
|
||||
{
|
||||
protocol->provider.log(protocol->user_data, 0, "begin authenticate");
|
||||
|
||||
struct wfp_credentials credentials;
|
||||
wfp_impl_credentials_init(&credentials);
|
||||
|
||||
@ -128,10 +137,10 @@ static void wfp_impl_client_protocol_authenticate(
|
||||
char const * cred_type = wfp_impl_credentials_get_type(&credentials);
|
||||
|
||||
wfp_jsonrpc_proxy_invoke(
|
||||
protocol->proxy,
|
||||
&wfp_impl_client_protocol_on_authenticate_finished,
|
||||
protocol,
|
||||
"authenticate",
|
||||
protocol->proxy,
|
||||
&wfp_impl_client_protocol_on_authenticate_finished,
|
||||
protocol,
|
||||
"authenticate",
|
||||
"sj",
|
||||
cred_type, &wfp_impl_credentials_write, &credentials);
|
||||
|
||||
@ -141,12 +150,15 @@ static void wfp_impl_client_protocol_authenticate(
|
||||
static void wfp_impl_client_protocol_handshake(
|
||||
struct wfp_client_protocol * protocol)
|
||||
{
|
||||
protocol->provider.log(protocol->user_data, 0, "begin connection handshake");
|
||||
|
||||
if (wfp_impl_provider_is_authentication_enabled(&protocol->provider))
|
||||
{
|
||||
wfp_impl_client_protocol_authenticate(protocol);
|
||||
}
|
||||
else
|
||||
{
|
||||
protocol->provider.log(protocol->user_data, 0, "skip authentication");
|
||||
wfp_impl_client_protocol_add_filesystem(protocol);
|
||||
}
|
||||
}
|
||||
@ -159,7 +171,7 @@ static int wfp_impl_client_protocol_callback(
|
||||
size_t len)
|
||||
{
|
||||
int result = 0;
|
||||
struct lws_protocols const * ws_protocol = lws_get_protocol(wsi);
|
||||
struct lws_protocols const * ws_protocol = lws_get_protocol(wsi);
|
||||
struct wfp_client_protocol * protocol = (NULL != ws_protocol) ? ws_protocol->user: NULL;
|
||||
|
||||
if (NULL != protocol)
|
||||
@ -169,24 +181,28 @@ static int wfp_impl_client_protocol_callback(
|
||||
switch (reason)
|
||||
{
|
||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
||||
protocol->provider.log(protocol->user_data, 0, "connection established");
|
||||
wfp_impl_client_protocol_handshake(protocol);
|
||||
break;
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
protocol->provider.log(protocol->user_data, 0, "connect error");
|
||||
protocol->is_connected = false;
|
||||
protocol->provider.disconnected(protocol->user_data);
|
||||
break;
|
||||
case LWS_CALLBACK_CLIENT_CLOSED:
|
||||
protocol->provider.log(protocol->user_data, 0, "connection closed");
|
||||
protocol->is_connected = false;
|
||||
protocol->provider.disconnected(protocol->user_data);
|
||||
protocol->provider.disconnected(protocol->user_data);
|
||||
protocol->wsi = NULL;
|
||||
break;
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||
protocol->provider.log(protocol->user_data, 0, "received: \"%.*s\"", len, in);
|
||||
wfp_impl_client_protocol_process(protocol, in, len);
|
||||
break;
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
// fall-through
|
||||
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
||||
if (wsi == protocol->wsi)
|
||||
if (wsi == protocol->wsi)
|
||||
{
|
||||
if (protocol->is_shutdown_requested)
|
||||
{
|
||||
@ -194,8 +210,10 @@ static int wfp_impl_client_protocol_callback(
|
||||
}
|
||||
else if (!wfp_slist_empty(&protocol->messages))
|
||||
{
|
||||
|
||||
struct wfp_slist_item * item = wfp_slist_remove_first(&protocol->messages);
|
||||
struct wfp_message * message = wfp_container_of(item, struct wfp_message, item);
|
||||
protocol->provider.log(protocol->user_data, 0, "send: \"%.*s\"", message->length, message->data);
|
||||
lws_write(wsi, (unsigned char*) message->data, message->length, LWS_WRITE_TEXT);
|
||||
wfp_message_dispose(message);
|
||||
|
||||
@ -207,7 +225,7 @@ static int wfp_impl_client_protocol_callback(
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,6 +247,7 @@ static void wfp_impl_client_protocol_send(
|
||||
void wfp_impl_client_protocol_init(
|
||||
struct wfp_client_protocol * protocol,
|
||||
struct wfp_provider const * provider,
|
||||
char const * fs_name,
|
||||
void * user_data)
|
||||
{
|
||||
protocol->is_connected = false;
|
||||
@ -243,6 +262,7 @@ void wfp_impl_client_protocol_init(
|
||||
protocol->timer_manager = wfp_timer_manager_create();
|
||||
protocol->proxy = wfp_jsonrpc_proxy_create(protocol->timer_manager, WFP_DEFAULT_TIMEOUT, &wfp_impl_client_protocol_send, protocol);
|
||||
|
||||
protocol->fs_name = strdup(fs_name);
|
||||
protocol->user_data = user_data;
|
||||
wfp_impl_provider_init_from_prototype(&protocol->provider, provider);
|
||||
}
|
||||
@ -253,13 +273,14 @@ void wfp_impl_client_protocol_cleanup(
|
||||
wfp_jsonrpc_proxy_dispose(protocol->proxy);
|
||||
wfp_timer_manager_dispose(protocol->timer_manager);
|
||||
wfp_message_queue_cleanup(&protocol->messages);
|
||||
free(protocol->fs_name);
|
||||
}
|
||||
|
||||
struct wfp_client_protocol * wfp_impl_client_protocol_create(
|
||||
struct wfp_client_config const * config)
|
||||
{
|
||||
struct wfp_client_protocol * protocol = malloc(sizeof(struct wfp_client_protocol));
|
||||
wfp_impl_client_protocol_init(protocol, &config->provider, config->user_data);
|
||||
wfp_impl_client_protocol_init(protocol, &config->provider, config->fs_name, config->user_data);
|
||||
|
||||
return protocol;
|
||||
}
|
||||
@ -311,7 +332,7 @@ void wfp_impl_client_protocol_connect(
|
||||
{
|
||||
protocol->provider.disconnected(protocol->user_data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void wfp_impl_client_protocol_disconnect(
|
||||
|
@ -23,6 +23,7 @@ struct wfp_client_protocol
|
||||
bool is_shutdown_requested;
|
||||
struct wfp_request request;
|
||||
struct wfp_provider provider;
|
||||
char * fs_name;
|
||||
void * user_data;
|
||||
struct lws * wsi;
|
||||
struct wfp_timer_manager * timer_manager;
|
||||
@ -33,6 +34,7 @@ struct wfp_client_protocol
|
||||
extern void wfp_impl_client_protocol_init(
|
||||
struct wfp_client_protocol * protocol,
|
||||
struct wfp_provider const * provider,
|
||||
char const * fs_name,
|
||||
void * user_data);
|
||||
|
||||
extern void wfp_impl_client_protocol_cleanup(
|
||||
@ -57,7 +59,7 @@ extern void wfp_impl_client_protocol_disconnect(
|
||||
struct wfp_client_protocol * protocol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -28,7 +28,7 @@ struct wfp_impl_method
|
||||
};
|
||||
|
||||
static void wfp_impl_provider_invoke_method(
|
||||
struct wfp_impl_invokation_context * context,
|
||||
struct wfp_impl_invokation_context * context,
|
||||
char const * method_name,
|
||||
struct wfp_json const * params,
|
||||
int id)
|
||||
@ -70,6 +70,7 @@ void wfp_impl_provider_init(
|
||||
provider->connected = &wfp_impl_connected_default;
|
||||
provider->disconnected = &wfp_impl_disconnected_default;
|
||||
provider->get_credentials = NULL;
|
||||
provider->log = &wfp_impl_log_default;
|
||||
}
|
||||
|
||||
void wfp_impl_provider_init_from_prototype(
|
||||
@ -85,6 +86,7 @@ void wfp_impl_provider_init_from_prototype(
|
||||
provider->connected = prototype->connected;
|
||||
provider->disconnected = prototype->disconnected;
|
||||
provider->get_credentials = prototype->get_credentials;
|
||||
provider->log = prototype->log;
|
||||
}
|
||||
|
||||
void wfp_impl_provider_invoke(
|
||||
@ -120,9 +122,22 @@ void wfp_impl_disconnected_default(
|
||||
// empty
|
||||
}
|
||||
|
||||
void wfp_impl_log_default(
|
||||
void * user_data,
|
||||
int level,
|
||||
char const * format,
|
||||
...)
|
||||
{
|
||||
(void) user_data;
|
||||
(void) level;
|
||||
(void) format;
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
bool wfp_impl_provider_is_authentication_enabled(
|
||||
struct wfp_provider * provider)
|
||||
{
|
||||
return (NULL != provider->get_credentials);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <cstdarg>
|
||||
#endif
|
||||
|
||||
#include "webfuse_provider/client_config.h"
|
||||
@ -26,6 +29,7 @@ struct wfp_provider
|
||||
wfp_close_fn * close;
|
||||
wfp_read_fn * read;
|
||||
wfp_get_credentials_fn * get_credentials;
|
||||
wfp_log_fn * log;
|
||||
};
|
||||
|
||||
struct wfp_impl_invokation_context
|
||||
@ -49,15 +53,21 @@ extern void wfp_impl_provider_invoke(
|
||||
|
||||
extern bool wfp_impl_provider_is_authentication_enabled(
|
||||
struct wfp_provider * provider);
|
||||
|
||||
|
||||
extern void wfp_impl_connected_default(
|
||||
void * user_data);
|
||||
|
||||
extern void wfp_impl_disconnected_default(
|
||||
void * user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern void wfp_impl_log_default(
|
||||
void * user_data,
|
||||
int level,
|
||||
char const * format,
|
||||
...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,4 +1,5 @@
|
||||
project('webfuse-provider', 'c', 'cpp', version: '0.3.0', license: 'LGPL-3.0+')
|
||||
project('webfuse-provider', 'c', 'cpp', version: '0.3.0', license: 'LGPL-3.0+',
|
||||
default_options: ['c_std=gnu99', 'cpp_std=gnu++14'])
|
||||
|
||||
without_tests = get_option('without_tests')
|
||||
without_examples = get_option('without_examples')
|
||||
@ -87,7 +88,7 @@ pkg_config.generate(
|
||||
|
||||
if not without_tests
|
||||
|
||||
gtest_dep = dependency('gtest', version: '>=1.10.0', fallback: ['gtest', 'gtest_dep'])
|
||||
gtest_dep = dependency('gtest', version: '>=1.10.0', fallback: ['gtest', 'gtest_dep'])
|
||||
gmock_main_dep = dependency('gmock_main', version: '>=1.10.0', fallback: ['gtest', 'gmock_main_dep'])
|
||||
|
||||
openssl = find_program('openssl')
|
||||
@ -180,4 +181,4 @@ executable('static-filesystem-provider',
|
||||
dependencies: [webfuse_provider_dep])
|
||||
|
||||
|
||||
endif
|
||||
endif
|
||||
|
@ -13,8 +13,10 @@
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
using webfuse_test::WsServer;
|
||||
using webfuse_test::MockProviderClient;
|
||||
@ -37,7 +39,10 @@ class ClientProtocolFixture
|
||||
public:
|
||||
explicit ClientProtocolFixture(IProviderClient& client, bool enableAuthentication = false)
|
||||
{
|
||||
server = new WsServer(WFP_PROTOCOL_NAME_ADAPTER_SERVER);
|
||||
server = new WsServer(WFP_PROTOCOL_NAME_ADAPTER_SERVER,
|
||||
[&](std::string const& message) mutable {
|
||||
OnMessageReceived(message);
|
||||
});
|
||||
|
||||
config = wfp_client_config_create();
|
||||
client.AttachTo(config, enableAuthentication);
|
||||
@ -67,7 +72,7 @@ public:
|
||||
{
|
||||
TimeoutWatcher watcher(DEFAULT_TIMEOUT);
|
||||
|
||||
wfp_client_protocol_connect(protocol, context, server->GetUrl().c_str());
|
||||
wfp_client_protocol_connect(protocol, context, server->GetUrl().c_str());
|
||||
while (!server->IsConnected())
|
||||
{
|
||||
watcher.check();
|
||||
@ -85,15 +90,36 @@ public:
|
||||
server->SendMessage(request);
|
||||
}
|
||||
|
||||
void OnMessageReceived(std::string const message)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
recv_queue.push(message);
|
||||
}
|
||||
lws_cancel_service(context);
|
||||
}
|
||||
|
||||
std::string ReceiveMessage()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
std::string result;
|
||||
if (!recv_queue.empty())
|
||||
{
|
||||
result = recv_queue.front();
|
||||
recv_queue.pop();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ReceiveMessageFromClient()
|
||||
{
|
||||
TimeoutWatcher watcher(DEFAULT_TIMEOUT);
|
||||
std::string result = server->ReceiveMessage();
|
||||
std::string result = ReceiveMessage();
|
||||
while (result.empty())
|
||||
{
|
||||
watcher.check();
|
||||
lws_service(context, 0);
|
||||
result = server->ReceiveMessage();
|
||||
result = ReceiveMessage();
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -128,7 +154,7 @@ public:
|
||||
wfp_json const * username = wfp_impl_json_object_get(credentials, "username");
|
||||
ASSERT_TRUE(wfp_impl_json_is_string(username));
|
||||
ASSERT_STREQ(expected_username.c_str(), wfp_impl_json_string_get(username));
|
||||
|
||||
|
||||
wfp_json const * password = wfp_impl_json_object_get(credentials, "password");
|
||||
ASSERT_TRUE(wfp_impl_json_is_string(password));
|
||||
ASSERT_STREQ(expected_password.c_str(), wfp_impl_json_string_get(password));
|
||||
@ -171,6 +197,8 @@ private:
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_protocols protocols[2];
|
||||
struct lws_context * context;
|
||||
std::queue<std::string> recv_queue;
|
||||
std::mutex mutex;
|
||||
|
||||
};
|
||||
|
||||
@ -217,7 +245,7 @@ TEST(client_protocol, connect_with_username_authentication)
|
||||
EXPECT_CALL(provider, OnConnected()).Times(AtMost(1));
|
||||
EXPECT_CALL(provider, OnDisconnected()).Times(1);
|
||||
EXPECT_CALL(provider, GetCredentials(_)).Times(1).WillOnce(Invoke(GetCredentials));
|
||||
|
||||
|
||||
fixture.Connect();
|
||||
if (HasFatalFailure()) { return; }
|
||||
|
||||
@ -253,4 +281,4 @@ TEST(client_protocol, getattr)
|
||||
ASSERT_FALSE(response.empty());
|
||||
|
||||
fixture.Disconnect();
|
||||
}
|
||||
}
|
||||
|
@ -101,12 +101,10 @@ public:
|
||||
info.mounts = NULL;
|
||||
info.protocols = protocols;
|
||||
info.vhost_name = "localhost";
|
||||
info.ws_ping_pong_interval = 10;
|
||||
// info.ws_ping_pong_interval = 10;
|
||||
info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;
|
||||
info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
|
||||
|
||||
context = lws_create_context(&info);
|
||||
|
||||
if (use_tls)
|
||||
{
|
||||
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
@ -114,9 +112,11 @@ public:
|
||||
info.ssl_private_key_filepath = "server-key.pem";
|
||||
}
|
||||
|
||||
context = lws_create_context(&info);
|
||||
|
||||
struct lws_vhost * vhost = lws_create_vhost(context, &info);
|
||||
int port = lws_get_vhost_port(vhost);
|
||||
std::ostringstream stream;
|
||||
std::ostringstream stream;
|
||||
stream << (use_tls ? "wss://" : "ws://") << "localhost:" << port << "/";
|
||||
url = stream.str();
|
||||
|
||||
@ -149,7 +149,7 @@ public:
|
||||
std::string Invoke(std::string const & method, std::string const & params)
|
||||
{
|
||||
std::promise<std::string> response;
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
message = &response;
|
||||
id++;
|
||||
@ -220,7 +220,7 @@ public:
|
||||
lws_callback_on_writable(wsi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wfp_impl_json_doc_dispose(doc);
|
||||
}
|
||||
}
|
||||
@ -337,4 +337,4 @@ std::string WebfuseServer::ReadDir(int inode)
|
||||
return d->Invoke("readdir", params.str());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,10 @@ class WsServer::Private : IServer
|
||||
Private(Private const &) = delete;
|
||||
Private & operator=(Private const &) = delete;
|
||||
public:
|
||||
Private(std::string const & protocol, int port);
|
||||
Private(
|
||||
std::string const & protocol,
|
||||
std::function<void(std::string const &)> handleMessage,
|
||||
int port);
|
||||
~Private();
|
||||
bool IsConnected();
|
||||
std::string GetUrl() const;
|
||||
@ -45,6 +48,7 @@ public:
|
||||
private:
|
||||
static void run(Private * self);
|
||||
std::string protocol_;
|
||||
std::function<void(std::string const &)> handleMessage_;
|
||||
int port_;
|
||||
bool is_connected;
|
||||
bool is_shutdown_requested;
|
||||
@ -55,7 +59,6 @@ private:
|
||||
std::thread context;
|
||||
std::mutex mutex;
|
||||
std::queue<std::string> writeQueue;
|
||||
std::queue<std::string> recvQueue;
|
||||
};
|
||||
|
||||
}
|
||||
@ -107,8 +110,11 @@ static int wfp_test_utils_ws_server_callback(
|
||||
namespace webfuse_test
|
||||
{
|
||||
|
||||
WsServer::WsServer(std::string const & protocol, int port)
|
||||
: d(new Private(protocol, port))
|
||||
WsServer::WsServer(
|
||||
std::string const & protocol,
|
||||
std::function<void(std::string const &)> handleMessage,
|
||||
int port)
|
||||
: d(new Private(protocol, handleMessage, port))
|
||||
{
|
||||
|
||||
}
|
||||
@ -128,19 +134,18 @@ void WsServer::SendMessage(std::string const & message)
|
||||
d->SendMessage(message);
|
||||
}
|
||||
|
||||
std::string WsServer::ReceiveMessage()
|
||||
{
|
||||
return d->ReceiveMessage();
|
||||
}
|
||||
|
||||
std::string WsServer::GetUrl() const
|
||||
{
|
||||
return d->GetUrl();
|
||||
}
|
||||
|
||||
|
||||
WsServer::Private::Private(std::string const & protocol, int port)
|
||||
WsServer::Private::Private(
|
||||
std::string const & protocol,
|
||||
std::function<void(std::string const &)> handleMessage,
|
||||
int port)
|
||||
: protocol_(protocol)
|
||||
, handleMessage_(handleMessage)
|
||||
, port_(port)
|
||||
, is_connected(false)
|
||||
, is_shutdown_requested(false)
|
||||
@ -160,7 +165,7 @@ WsServer::Private::Private(std::string const & protocol, int port)
|
||||
info.mounts = NULL;
|
||||
info.protocols =ws_protocols;
|
||||
info.vhost_name = "localhost";
|
||||
info.ws_ping_pong_interval = 10;
|
||||
// info.ws_ping_pong_interval = 10;
|
||||
info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;
|
||||
info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
|
||||
|
||||
@ -270,25 +275,16 @@ void WsServer::Private::SendMessage(std::string const & message)
|
||||
|
||||
void WsServer::Private::OnMessageReceived(struct lws * wsi, char const * data, size_t length)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (wsi == wsi_)
|
||||
bool handleMessage;
|
||||
{
|
||||
recvQueue.push(std::string(data, length));
|
||||
}
|
||||
}
|
||||
|
||||
std::string WsServer::Private::ReceiveMessage()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
|
||||
std::string message;
|
||||
if (!recvQueue.empty())
|
||||
{
|
||||
message = recvQueue.front();
|
||||
recvQueue.pop();
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
handleMessage = (wsi == wsi_);
|
||||
}
|
||||
|
||||
return message;
|
||||
if (handleMessage)
|
||||
{
|
||||
handleMessage_(std::string(data, length));
|
||||
}
|
||||
}
|
||||
|
||||
std::string WsServer::Private::GetUrl() const
|
||||
@ -299,4 +295,4 @@ std::string WsServer::Private::GetUrl() const
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define WFP_TEST_UTILS_WS_SERVER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
namespace webfuse_test
|
||||
{
|
||||
@ -11,12 +12,14 @@ class WsServer
|
||||
WsServer(WsServer const &) = delete;
|
||||
WsServer & operator=(WsServer const &) = delete;
|
||||
public:
|
||||
WsServer(std::string const & protocol, int port = 0);
|
||||
WsServer(
|
||||
std::string const & protocol,
|
||||
std::function<void(std::string const &)> handleMessage,
|
||||
int port = 0);
|
||||
~WsServer();
|
||||
bool IsConnected();
|
||||
std::string GetUrl() const;
|
||||
void SendMessage(std::string const & message);
|
||||
std::string ReceiveMessage();
|
||||
private:
|
||||
class Private;
|
||||
Private * d;
|
||||
|
Loading…
Reference in New Issue
Block a user