fixed unit tests; added logging support; allow to specify filesystem name

pull/4/head
Falk Werner 4 years ago
parent 8140afe2ab
commit c26342cefd

@ -16,6 +16,7 @@ struct config
char * url; char * url;
struct wfp_client_config * client_config; struct wfp_client_config * client_config;
bool show_help; bool show_help;
bool is_verbose;
}; };
enum fs_entry_type enum fs_entry_type
@ -37,6 +38,8 @@ struct fs_entry
struct fs struct fs
{ {
bool is_verbose;
bool connection_closed;
struct fs_entry const * entries; 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" "Usage: webfuse-provider -u <url> [-k <key_path>] [-c <cert_path>]\n"
"\n" "\n"
"Options:\n" "Options:\n"
"\t-u, --url URL of webfuse server (required)\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-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-c, --cert_path Path to certificate of provider (defautl: not set, TLS disabled)\n"
"\t-h, --help prints this message\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" "\n"
"Example:\n" "Example:\n"
"\twebfuse-provider -u ws://localhost:8080/\n" "\twebfuse-provider -u ws://localhost:8080/\n"
@ -70,16 +75,20 @@ static int parse_arguments(
{"url", required_argument, NULL, 'u'}, {"url", required_argument, NULL, 'u'},
{"key_path", required_argument, NULL, 'k'}, {"key_path", required_argument, NULL, 'k'},
{"cert_path", required_argument, NULL, 'c'}, {"cert_path", required_argument, NULL, 'c'},
{"filesystem_name", required_argument, NULL, 'n'},
{"verbose", required_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
optind = 0;
opterr = 0;
int result = EXIT_SUCCESS; int result = EXIT_SUCCESS;
bool finished = false; bool finished = false;
while (!finished) while (!finished)
{ {
int option_index = 0; 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) switch (c)
{ {
@ -100,6 +109,12 @@ static int parse_arguments(
case 'c': case 'c':
wfp_client_config_set_certpath(config->client_config, optarg); wfp_client_config_set_certpath(config->client_config, optarg);
break; break;
case 'n':
wfp_client_config_set_fsname(config->client_config, optarg);
break;
case 'v':
config->is_verbose = true;
break;
default: default:
fprintf(stderr, "error: unknown argument\n"); fprintf(stderr, "error: unknown argument\n");
finished = true; finished = true;
@ -133,7 +148,7 @@ static struct fs_entry const * fs_getentry(
{ {
return entry; return entry;
} }
} }
return NULL; return NULL;
} }
@ -269,7 +284,7 @@ static void fs_open(
else else
{ {
wfp_respond_error(request, WFP_BAD_ACCESS_DENIED); wfp_respond_error(request, WFP_BAD_ACCESS_DENIED);
} }
} }
else else
{ {
@ -306,7 +321,7 @@ static void fs_read(
else else
{ {
wfp_respond_error(request, WFP_BAD); wfp_respond_error(request, WFP_BAD);
} }
} }
else else
{ {
@ -322,11 +337,43 @@ static void on_interrupt(int signal_id)
shutdown_requested = true; 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[]) int main(int argc, char* argv[])
{ {
struct config config; struct config config;
config.url = NULL; config.url = NULL;
config.show_help = false; config.show_help = false;
config.is_verbose = false;
config.client_config = wfp_client_config_create(); config.client_config = wfp_client_config_create();
int result = parse_arguments(argc, argv, &config); int result = parse_arguments(argc, argv, &config);
@ -349,6 +396,8 @@ int main(int argc, char* argv[])
struct fs fs = struct fs fs =
{ {
.is_verbose = config.is_verbose,
.connection_closed = false,
.entries = entries .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_onreaddir(config.client_config, &fs_readdir);
wfp_client_config_set_onopen(config.client_config, &fs_open); wfp_client_config_set_onopen(config.client_config, &fs_open);
wfp_client_config_set_onread(config.client_config, &fs_read); 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); struct wfp_client * client = wfp_client_create(config.client_config);
wfp_client_connect(client, config.url); wfp_client_connect(client, config.url);
while (!shutdown_requested) while ((!shutdown_requested) && (!fs.connection_closed))
{ {
wfp_client_service(client); wfp_client_service(client);
} }
wfp_client_dispose(client); wfp_client_dispose(client);
} }
if (config.show_help) if (config.show_help)
{ {
@ -380,4 +432,4 @@ int main(int argc, char* argv[])
free(config.url); free(config.url);
wfp_client_config_dispose(config.client_config); wfp_client_config_dispose(config.client_config);
return result; return result;
} }

@ -16,6 +16,12 @@
#include <webfuse_provider/operation/read.h> #include <webfuse_provider/operation/read.h>
#include <webfuse_provider/credentials.h> #include <webfuse_provider/credentials.h>
#ifndef __cplusplus
#include <stdarg.h>
#else
#include <cstdarg>
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -45,6 +51,20 @@ typedef void wfp_connected_fn(
typedef void wfp_disconnected_fn( typedef void wfp_disconnected_fn(
void * user_data); 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. /// \brief Creates a new client configuration.
/// ///
@ -225,13 +245,33 @@ extern WFP_API void wfp_client_config_set_onread(
/// \brief Enabled authentication. /// \brief Enabled authentication.
/// ///
/// \param config pointer to client configuration /// \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. // needed.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
extern WFP_API void wfp_client_config_enable_authentication( extern WFP_API void wfp_client_config_enable_authentication(
struct wfp_client_config * config, struct wfp_client_config * config,
wfp_get_credentials_fn * get_credentials); 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 #ifdef __cplusplus
} }
#endif #endif

@ -165,6 +165,20 @@ void wfp_client_config_enable_authentication(
wfp_impl_client_config_enable_authentication(config, get_credentials); 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 // protocol

@ -28,9 +28,9 @@ struct wfp_client * wfp_impl_client_create(
struct wfp_client_config * config) struct wfp_client_config * config)
{ {
wfp_impl_lwslog_disable(); wfp_impl_lwslog_disable();
struct wfp_client * client = malloc(sizeof(struct wfp_client)); 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); memset(client->protocols, 0, sizeof(struct lws_protocols) * WFP_CLIENT_PROTOCOL_COUNT);
wfp_impl_client_protocol_init_lws(&client->protocol, &client->protocols[0]); wfp_impl_client_protocol_init_lws(&client->protocol, &client->protocols[0]);
@ -65,7 +65,7 @@ void wfp_impl_client_dispose(
struct wfp_client * client) struct wfp_client * client)
{ {
lws_context_destroy(client->context); lws_context_destroy(client->context);
wfp_impl_client_protocol_cleanup(&client->protocol); wfp_impl_client_protocol_cleanup(&client->protocol);
free(client); free(client);
} }

@ -11,6 +11,7 @@ struct wfp_client_config * wfp_impl_client_config_create(void)
config->key_path = NULL; config->key_path = NULL;
config->cert_path = NULL; config->cert_path = NULL;
config->ca_filepath = NULL; config->ca_filepath = NULL;
config->fs_name = strdup("cprovider");
return config; return config;
} }
@ -18,6 +19,7 @@ struct wfp_client_config * wfp_impl_client_config_create(void)
void wfp_impl_client_config_dispose( void wfp_impl_client_config_dispose(
struct wfp_client_config * config) struct wfp_client_config * config)
{ {
free(config->fs_name);
free(config->key_path); free(config->key_path);
free(config->cert_path); free(config->cert_path);
free(config->ca_filepath); free(config->ca_filepath);
@ -52,7 +54,7 @@ void wfp_impl_client_config_set_ca_filepath(
char const * ca_filepath) char const * ca_filepath)
{ {
free(config->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( void wfp_impl_client_config_set_onconnected(
@ -117,3 +119,18 @@ void wfp_impl_client_config_enable_authentication(
{ {
config->provider.get_credentials = get_credentials; 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 * key_path;
char * cert_path; char * cert_path;
char * ca_filepath; char * ca_filepath;
char * fs_name;
}; };
extern struct wfp_client_config * wfp_impl_client_config_create(void); 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, struct wfp_client_config * config,
wfp_get_credentials_fn * get_credentials); 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 #ifdef __cplusplus
} }
#endif #endif

@ -35,7 +35,7 @@ static void wfp_impl_client_protocol_respond(
} }
static void wfp_impl_client_protocol_process( static void wfp_impl_client_protocol_process(
struct wfp_client_protocol * protocol, struct wfp_client_protocol * protocol,
char * data, char * data,
size_t length) 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( wfp_impl_client_protocol_on_add_filesystem_finished(
void * user_data, void * user_data,
struct wfp_json const * result, 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; struct wfp_client_protocol * protocol = user_data;
if (NULL == protocol->wsi) { return; } if (NULL == protocol->wsi) { return; }
if (NULL != result) 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->is_connected = true;
protocol->provider.connected(protocol->user_data); protocol->provider.connected(protocol->user_data);
} }
else else
{ {
protocol->provider.log(protocol->user_data, 0, "add filesystem failed");
protocol->is_shutdown_requested = true; protocol->is_shutdown_requested = true;
lws_callback_on_writable(protocol->wsi); lws_callback_on_writable(protocol->wsi);
} }
} }
static void wfp_impl_client_protocol_add_filesystem( static void wfp_impl_client_protocol_add_filesystem(
struct wfp_client_protocol * protocol) struct wfp_client_protocol * protocol)
{ {
protocol->provider.log(protocol->user_data, 0, "begin add filesystem");
wfp_jsonrpc_proxy_invoke( wfp_jsonrpc_proxy_invoke(
protocol->proxy, protocol->proxy,
&wfp_impl_client_protocol_on_add_filesystem_finished, &wfp_impl_client_protocol_on_add_filesystem_finished,
protocol, protocol,
"add_filesystem", "add_filesystem",
"s", "s",
"cprovider"); protocol->fs_name);
} }
static void static void
wfp_impl_client_protocol_on_authenticate_finished( wfp_impl_client_protocol_on_authenticate_finished(
void * user_data, void * user_data,
struct wfp_json const * result, 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; struct wfp_client_protocol * protocol = user_data;
if (NULL == protocol->wsi) { return; } if (NULL == protocol->wsi) { return; }
if (NULL != result) if (NULL != result)
{ {
protocol->provider.log(protocol->user_data, 0, "authentication finished");
wfp_impl_client_protocol_add_filesystem(protocol); wfp_impl_client_protocol_add_filesystem(protocol);
} }
else else
{ {
protocol->provider.log(protocol->user_data, 0, "authentication failed");
protocol->is_shutdown_requested = true; protocol->is_shutdown_requested = true;
lws_callback_on_writable(protocol->wsi); lws_callback_on_writable(protocol->wsi);
} }
} }
static void wfp_impl_client_protocol_authenticate( static void wfp_impl_client_protocol_authenticate(
struct wfp_client_protocol * protocol) struct wfp_client_protocol * protocol)
{ {
protocol->provider.log(protocol->user_data, 0, "begin authenticate");
struct wfp_credentials credentials; struct wfp_credentials credentials;
wfp_impl_credentials_init(&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); char const * cred_type = wfp_impl_credentials_get_type(&credentials);
wfp_jsonrpc_proxy_invoke( wfp_jsonrpc_proxy_invoke(
protocol->proxy, protocol->proxy,
&wfp_impl_client_protocol_on_authenticate_finished, &wfp_impl_client_protocol_on_authenticate_finished,
protocol, protocol,
"authenticate", "authenticate",
"sj", "sj",
cred_type, &wfp_impl_credentials_write, &credentials); 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( static void wfp_impl_client_protocol_handshake(
struct wfp_client_protocol * protocol) struct wfp_client_protocol * protocol)
{ {
protocol->provider.log(protocol->user_data, 0, "begin connection handshake");
if (wfp_impl_provider_is_authentication_enabled(&protocol->provider)) if (wfp_impl_provider_is_authentication_enabled(&protocol->provider))
{ {
wfp_impl_client_protocol_authenticate(protocol); wfp_impl_client_protocol_authenticate(protocol);
} }
else else
{ {
protocol->provider.log(protocol->user_data, 0, "skip authentication");
wfp_impl_client_protocol_add_filesystem(protocol); wfp_impl_client_protocol_add_filesystem(protocol);
} }
} }
@ -159,7 +171,7 @@ static int wfp_impl_client_protocol_callback(
size_t len) size_t len)
{ {
int result = 0; 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; struct wfp_client_protocol * protocol = (NULL != ws_protocol) ? ws_protocol->user: NULL;
if (NULL != protocol) if (NULL != protocol)
@ -169,24 +181,28 @@ static int wfp_impl_client_protocol_callback(
switch (reason) switch (reason)
{ {
case LWS_CALLBACK_CLIENT_ESTABLISHED: case LWS_CALLBACK_CLIENT_ESTABLISHED:
protocol->provider.log(protocol->user_data, 0, "connection established");
wfp_impl_client_protocol_handshake(protocol); wfp_impl_client_protocol_handshake(protocol);
break; break;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
protocol->provider.log(protocol->user_data, 0, "connect error");
protocol->is_connected = false; protocol->is_connected = false;
protocol->provider.disconnected(protocol->user_data); protocol->provider.disconnected(protocol->user_data);
break; break;
case LWS_CALLBACK_CLIENT_CLOSED: case LWS_CALLBACK_CLIENT_CLOSED:
protocol->provider.log(protocol->user_data, 0, "connection closed");
protocol->is_connected = false; protocol->is_connected = false;
protocol->provider.disconnected(protocol->user_data); protocol->provider.disconnected(protocol->user_data);
protocol->wsi = NULL; protocol->wsi = NULL;
break; break;
case LWS_CALLBACK_CLIENT_RECEIVE: case LWS_CALLBACK_CLIENT_RECEIVE:
protocol->provider.log(protocol->user_data, 0, "received: \"%.*s\"", len, in);
wfp_impl_client_protocol_process(protocol, in, len); wfp_impl_client_protocol_process(protocol, in, len);
break; break;
case LWS_CALLBACK_SERVER_WRITEABLE: case LWS_CALLBACK_SERVER_WRITEABLE:
// fall-through // fall-through
case LWS_CALLBACK_CLIENT_WRITEABLE: case LWS_CALLBACK_CLIENT_WRITEABLE:
if (wsi == protocol->wsi) if (wsi == protocol->wsi)
{ {
if (protocol->is_shutdown_requested) if (protocol->is_shutdown_requested)
{ {
@ -194,8 +210,10 @@ static int wfp_impl_client_protocol_callback(
} }
else if (!wfp_slist_empty(&protocol->messages)) else if (!wfp_slist_empty(&protocol->messages))
{ {
struct wfp_slist_item * item = wfp_slist_remove_first(&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); 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); lws_write(wsi, (unsigned char*) message->data, message->length, LWS_WRITE_TEXT);
wfp_message_dispose(message); wfp_message_dispose(message);
@ -207,7 +225,7 @@ static int wfp_impl_client_protocol_callback(
} }
break; break;
default: default:
break; break;
} }
} }
@ -229,6 +247,7 @@ static void wfp_impl_client_protocol_send(
void wfp_impl_client_protocol_init( void wfp_impl_client_protocol_init(
struct wfp_client_protocol * protocol, struct wfp_client_protocol * protocol,
struct wfp_provider const * provider, struct wfp_provider const * provider,
char const * fs_name,
void * user_data) void * user_data)
{ {
protocol->is_connected = false; protocol->is_connected = false;
@ -243,6 +262,7 @@ void wfp_impl_client_protocol_init(
protocol->timer_manager = wfp_timer_manager_create(); 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->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; protocol->user_data = user_data;
wfp_impl_provider_init_from_prototype(&protocol->provider, provider); 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_jsonrpc_proxy_dispose(protocol->proxy);
wfp_timer_manager_dispose(protocol->timer_manager); wfp_timer_manager_dispose(protocol->timer_manager);
wfp_message_queue_cleanup(&protocol->messages); wfp_message_queue_cleanup(&protocol->messages);
free(protocol->fs_name);
} }
struct wfp_client_protocol * wfp_impl_client_protocol_create( struct wfp_client_protocol * wfp_impl_client_protocol_create(
struct wfp_client_config const * config) struct wfp_client_config const * config)
{ {
struct wfp_client_protocol * protocol = malloc(sizeof(struct wfp_client_protocol)); 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; return protocol;
} }
@ -311,7 +332,7 @@ void wfp_impl_client_protocol_connect(
{ {
protocol->provider.disconnected(protocol->user_data); protocol->provider.disconnected(protocol->user_data);
} }
} }
void wfp_impl_client_protocol_disconnect( void wfp_impl_client_protocol_disconnect(

@ -23,6 +23,7 @@ struct wfp_client_protocol
bool is_shutdown_requested; bool is_shutdown_requested;
struct wfp_request request; struct wfp_request request;
struct wfp_provider provider; struct wfp_provider provider;
char * fs_name;
void * user_data; void * user_data;
struct lws * wsi; struct lws * wsi;
struct wfp_timer_manager * timer_manager; struct wfp_timer_manager * timer_manager;
@ -33,6 +34,7 @@ struct wfp_client_protocol
extern void wfp_impl_client_protocol_init( extern void wfp_impl_client_protocol_init(
struct wfp_client_protocol * protocol, struct wfp_client_protocol * protocol,
struct wfp_provider const * provider, struct wfp_provider const * provider,
char const * fs_name,
void * user_data); void * user_data);
extern void wfp_impl_client_protocol_cleanup( extern void wfp_impl_client_protocol_cleanup(
@ -57,7 +59,7 @@ extern void wfp_impl_client_protocol_disconnect(
struct wfp_client_protocol * protocol); struct wfp_client_protocol * protocol);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

@ -28,7 +28,7 @@ struct wfp_impl_method
}; };
static void wfp_impl_provider_invoke_method( static void wfp_impl_provider_invoke_method(
struct wfp_impl_invokation_context * context, struct wfp_impl_invokation_context * context,
char const * method_name, char const * method_name,
struct wfp_json const * params, struct wfp_json const * params,
int id) int id)
@ -70,6 +70,7 @@ void wfp_impl_provider_init(
provider->connected = &wfp_impl_connected_default; provider->connected = &wfp_impl_connected_default;
provider->disconnected = &wfp_impl_disconnected_default; provider->disconnected = &wfp_impl_disconnected_default;
provider->get_credentials = NULL; provider->get_credentials = NULL;
provider->log = &wfp_impl_log_default;
} }
void wfp_impl_provider_init_from_prototype( void wfp_impl_provider_init_from_prototype(
@ -85,6 +86,7 @@ void wfp_impl_provider_init_from_prototype(
provider->connected = prototype->connected; provider->connected = prototype->connected;
provider->disconnected = prototype->disconnected; provider->disconnected = prototype->disconnected;
provider->get_credentials = prototype->get_credentials; provider->get_credentials = prototype->get_credentials;
provider->log = prototype->log;
} }
void wfp_impl_provider_invoke( void wfp_impl_provider_invoke(
@ -120,9 +122,22 @@ void wfp_impl_disconnected_default(
// empty // 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( bool wfp_impl_provider_is_authentication_enabled(
struct wfp_provider * provider) struct wfp_provider * provider)
{ {
return (NULL != provider->get_credentials); return (NULL != provider->get_credentials);
} }

@ -3,6 +3,9 @@
#ifndef __cplusplus #ifndef __cplusplus
#include <stdbool.h> #include <stdbool.h>
#include <stdarg.h>
#else
#include <cstdarg>
#endif #endif
#include "webfuse_provider/client_config.h" #include "webfuse_provider/client_config.h"
@ -26,6 +29,7 @@ struct wfp_provider
wfp_close_fn * close; wfp_close_fn * close;
wfp_read_fn * read; wfp_read_fn * read;
wfp_get_credentials_fn * get_credentials; wfp_get_credentials_fn * get_credentials;
wfp_log_fn * log;
}; };
struct wfp_impl_invokation_context struct wfp_impl_invokation_context
@ -49,15 +53,21 @@ extern void wfp_impl_provider_invoke(
extern bool wfp_impl_provider_is_authentication_enabled( extern bool wfp_impl_provider_is_authentication_enabled(
struct wfp_provider * provider); struct wfp_provider * provider);
extern void wfp_impl_connected_default( extern void wfp_impl_connected_default(
void * user_data); void * user_data);
extern void wfp_impl_disconnected_default( extern void wfp_impl_disconnected_default(
void * user_data); void * user_data);
#ifdef __cplusplus extern void wfp_impl_log_default(
void * user_data,
int level,
char const * format,
...);
#ifdef __cplusplus
} }
#endif #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_tests = get_option('without_tests')
without_examples = get_option('without_examples') without_examples = get_option('without_examples')
@ -87,7 +88,7 @@ pkg_config.generate(
if not without_tests 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']) gmock_main_dep = dependency('gmock_main', version: '>=1.10.0', fallback: ['gtest', 'gmock_main_dep'])
openssl = find_program('openssl') openssl = find_program('openssl')
@ -180,4 +181,4 @@ executable('static-filesystem-provider',
dependencies: [webfuse_provider_dep]) dependencies: [webfuse_provider_dep])
endif endif

@ -13,8 +13,10 @@
#include <libwebsockets.h> #include <libwebsockets.h>
#include <cstring> #include <cstring>
#include <queue>
#include <sstream> #include <sstream>
#include <thread> #include <thread>
#include <mutex>
using webfuse_test::WsServer; using webfuse_test::WsServer;
using webfuse_test::MockProviderClient; using webfuse_test::MockProviderClient;
@ -37,7 +39,10 @@ class ClientProtocolFixture
public: public:
explicit ClientProtocolFixture(IProviderClient& client, bool enableAuthentication = false) 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(); config = wfp_client_config_create();
client.AttachTo(config, enableAuthentication); client.AttachTo(config, enableAuthentication);
@ -67,7 +72,7 @@ public:
{ {
TimeoutWatcher watcher(DEFAULT_TIMEOUT); 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()) while (!server->IsConnected())
{ {
watcher.check(); watcher.check();
@ -85,15 +90,36 @@ public:
server->SendMessage(request); 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() std::string ReceiveMessageFromClient()
{ {
TimeoutWatcher watcher(DEFAULT_TIMEOUT); TimeoutWatcher watcher(DEFAULT_TIMEOUT);
std::string result = server->ReceiveMessage(); std::string result = ReceiveMessage();
while (result.empty()) while (result.empty())
{ {
watcher.check(); watcher.check();
lws_service(context, 0); lws_service(context, 0);
result = server->ReceiveMessage(); result = ReceiveMessage();
} }
return result; return result;
@ -128,7 +154,7 @@ public:
wfp_json const * username = wfp_impl_json_object_get(credentials, "username"); wfp_json const * username = wfp_impl_json_object_get(credentials, "username");
ASSERT_TRUE(wfp_impl_json_is_string(username)); ASSERT_TRUE(wfp_impl_json_is_string(username));
ASSERT_STREQ(expected_username.c_str(), wfp_impl_json_string_get(username)); ASSERT_STREQ(expected_username.c_str(), wfp_impl_json_string_get(username));
wfp_json const * password = wfp_impl_json_object_get(credentials, "password"); wfp_json const * password = wfp_impl_json_object_get(credentials, "password");
ASSERT_TRUE(wfp_impl_json_is_string(password)); ASSERT_TRUE(wfp_impl_json_is_string(password));
ASSERT_STREQ(expected_password.c_str(), wfp_impl_json_string_get(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_context_creation_info info;
struct lws_protocols protocols[2]; struct lws_protocols protocols[2];
struct lws_context * context; 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, OnConnected()).Times(AtMost(1));
EXPECT_CALL(provider, OnDisconnected()).Times(1); EXPECT_CALL(provider, OnDisconnected()).Times(1);
EXPECT_CALL(provider, GetCredentials(_)).Times(1).WillOnce(Invoke(GetCredentials)); EXPECT_CALL(provider, GetCredentials(_)).Times(1).WillOnce(Invoke(GetCredentials));
fixture.Connect(); fixture.Connect();
if (HasFatalFailure()) { return; } if (HasFatalFailure()) { return; }
@ -253,4 +281,4 @@ TEST(client_protocol, getattr)
ASSERT_FALSE(response.empty()); ASSERT_FALSE(response.empty());
fixture.Disconnect(); fixture.Disconnect();
} }

@ -101,12 +101,10 @@ public:
info.mounts = NULL; info.mounts = NULL;
info.protocols = protocols; info.protocols = protocols;
info.vhost_name = "localhost"; 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_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;
info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS; info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
context = lws_create_context(&info);
if (use_tls) if (use_tls)
{ {
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
@ -114,9 +112,11 @@ public:
info.ssl_private_key_filepath = "server-key.pem"; info.ssl_private_key_filepath = "server-key.pem";
} }
context = lws_create_context(&info);
struct lws_vhost * vhost = lws_create_vhost(context, &info); struct lws_vhost * vhost = lws_create_vhost(context, &info);
int port = lws_get_vhost_port(vhost); int port = lws_get_vhost_port(vhost);
std::ostringstream stream; std::ostringstream stream;
stream << (use_tls ? "wss://" : "ws://") << "localhost:" << port << "/"; stream << (use_tls ? "wss://" : "ws://") << "localhost:" << port << "/";
url = stream.str(); url = stream.str();
@ -149,7 +149,7 @@ public:
std::string Invoke(std::string const & method, std::string const & params) std::string Invoke(std::string const & method, std::string const & params)
{ {
std::promise<std::string> response; std::promise<std::string> response;
{ {
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
message = &response; message = &response;
id++; id++;
@ -220,7 +220,7 @@ public:
lws_callback_on_writable(wsi); lws_callback_on_writable(wsi);
} }
} }
wfp_impl_json_doc_dispose(doc); wfp_impl_json_doc_dispose(doc);
} }
} }
@ -337,4 +337,4 @@ std::string WebfuseServer::ReadDir(int inode)
return d->Invoke("readdir", params.str()); return d->Invoke("readdir", params.str());
} }
} }

@ -31,7 +31,10 @@ class WsServer::Private : IServer
Private(Private const &) = delete; Private(Private const &) = delete;
Private & operator=(Private const &) = delete; Private & operator=(Private const &) = delete;
public: public:
Private(std::string const & protocol, int port); Private(
std::string const & protocol,
std::function<void(std::string const &)> handleMessage,
int port);
~Private(); ~Private();
bool IsConnected(); bool IsConnected();
std::string GetUrl() const; std::string GetUrl() const;
@ -45,6 +48,7 @@ public:
private: private:
static void run(Private * self); static void run(Private * self);
std::string protocol_; std::string protocol_;
std::function<void(std::string const &)> handleMessage_;
int port_; int port_;
bool is_connected; bool is_connected;
bool is_shutdown_requested; bool is_shutdown_requested;
@ -55,7 +59,6 @@ private:
std::thread context; std::thread context;
std::mutex mutex; std::mutex mutex;
std::queue<std::string> writeQueue; 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 namespace webfuse_test
{ {
WsServer::WsServer(std::string const & protocol, int port) WsServer::WsServer(
: d(new Private(protocol, port)) 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); d->SendMessage(message);
} }
std::string WsServer::ReceiveMessage()
{
return d->ReceiveMessage();
}
std::string WsServer::GetUrl() const std::string WsServer::GetUrl() const
{ {
return d->GetUrl(); 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) : protocol_(protocol)
, handleMessage_(handleMessage)
, port_(port) , port_(port)
, is_connected(false) , is_connected(false)
, is_shutdown_requested(false) , is_shutdown_requested(false)
@ -160,7 +165,7 @@ WsServer::Private::Private(std::string const & protocol, int port)
info.mounts = NULL; info.mounts = NULL;
info.protocols =ws_protocols; info.protocols =ws_protocols;
info.vhost_name = "localhost"; 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_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;
info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS; 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) void WsServer::Private::OnMessageReceived(struct lws * wsi, char const * data, size_t length)
{ {
std::unique_lock<std::mutex> lock(mutex); bool handleMessage;
if (wsi == wsi_)
{ {
recvQueue.push(std::string(data, length)); std::unique_lock<std::mutex> lock(mutex);
handleMessage = (wsi == wsi_);
} }
}
std::string WsServer::Private::ReceiveMessage() if (handleMessage)
{
std::unique_lock<std::mutex> lock(mutex);
std::string message;
if (!recvQueue.empty())
{ {
message = recvQueue.front(); handleMessage_(std::string(data, length));
recvQueue.pop();
} }
return message;
} }
std::string WsServer::Private::GetUrl() const 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 #define WFP_TEST_UTILS_WS_SERVER_HPP
#include <string> #include <string>
#include <functional>
namespace webfuse_test namespace webfuse_test
{ {
@ -11,12 +12,14 @@ class WsServer
WsServer(WsServer const &) = delete; WsServer(WsServer const &) = delete;
WsServer & operator=(WsServer const &) = delete; WsServer & operator=(WsServer const &) = delete;
public: 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(); ~WsServer();
bool IsConnected(); bool IsConnected();
std::string GetUrl() const; std::string GetUrl() const;
void SendMessage(std::string const & message); void SendMessage(std::string const & message);
std::string ReceiveMessage();
private: private:
class Private; class Private;
Private * d; Private * d;

Loading…
Cancel
Save