From c26342cefd570c6c91c27dde9c62d74942393933 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Thu, 12 Nov 2020 20:36:05 +0100 Subject: [PATCH] fixed unit tests; added logging support; allow to specify filesystem name --- examples/provider/main.c | 74 ++++++++++++++++--- include/webfuse_provider/client_config.h | 42 ++++++++++- lib/webfuse_provider/api.c | 14 ++++ lib/webfuse_provider/impl/client.c | 6 +- lib/webfuse_provider/impl/client_config.c | 19 ++++- lib/webfuse_provider/impl/client_config.h | 9 +++ lib/webfuse_provider/impl/client_protocol.c | 59 ++++++++++----- lib/webfuse_provider/impl/client_protocol.h | 4 +- lib/webfuse_provider/impl/provider.c | 19 ++++- lib/webfuse_provider/impl/provider.h | 16 +++- meson.build | 7 +- .../provider/test_client_protocol.cc | 42 +++++++++-- .../test_util/webfuse_server.cc | 14 ++-- test/webfuse_provider/test_util/ws_server.cc | 48 ++++++------ test/webfuse_provider/test_util/ws_server.h | 7 +- 15 files changed, 294 insertions(+), 86 deletions(-) diff --git a/examples/provider/main.c b/examples/provider/main.c index 97e41a5..ac32f34 100644 --- a/examples/provider/main.c +++ b/examples/provider/main.c @@ -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 [-k ] [-c ]\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; -} \ No newline at end of file +} diff --git a/include/webfuse_provider/client_config.h b/include/webfuse_provider/client_config.h index 2345e62..c72f0f7 100644 --- a/include/webfuse_provider/client_config.h +++ b/include/webfuse_provider/client_config.h @@ -16,6 +16,12 @@ #include #include +#ifndef __cplusplus +#include +#else +#include +#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 diff --git a/lib/webfuse_provider/api.c b/lib/webfuse_provider/api.c index 0155dd5..f5e48d0 100644 --- a/lib/webfuse_provider/api.c +++ b/lib/webfuse_provider/api.c @@ -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 diff --git a/lib/webfuse_provider/impl/client.c b/lib/webfuse_provider/impl/client.c index 596cbaf..55ddf68 100644 --- a/lib/webfuse_provider/impl/client.c +++ b/lib/webfuse_provider/impl/client.c @@ -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); } diff --git a/lib/webfuse_provider/impl/client_config.c b/lib/webfuse_provider/impl/client_config.c index 26e0df5..11c6f66 100644 --- a/lib/webfuse_provider/impl/client_config.c +++ b/lib/webfuse_provider/impl/client_config.c @@ -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; +} diff --git a/lib/webfuse_provider/impl/client_config.h b/lib/webfuse_provider/impl/client_config.h index 49f565f..2433e9b 100644 --- a/lib/webfuse_provider/impl/client_config.h +++ b/lib/webfuse_provider/impl/client_config.h @@ -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 diff --git a/lib/webfuse_provider/impl/client_protocol.c b/lib/webfuse_provider/impl/client_protocol.c index f67fa4a..27594d5 100644 --- a/lib/webfuse_provider/impl/client_protocol.c +++ b/lib/webfuse_provider/impl/client_protocol.c @@ -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( diff --git a/lib/webfuse_provider/impl/client_protocol.h b/lib/webfuse_provider/impl/client_protocol.h index 60eec44..0922baa 100644 --- a/lib/webfuse_provider/impl/client_protocol.h +++ b/lib/webfuse_provider/impl/client_protocol.h @@ -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 diff --git a/lib/webfuse_provider/impl/provider.c b/lib/webfuse_provider/impl/provider.c index 2686c5f..726c136 100644 --- a/lib/webfuse_provider/impl/provider.c +++ b/lib/webfuse_provider/impl/provider.c @@ -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); } - diff --git a/lib/webfuse_provider/impl/provider.h b/lib/webfuse_provider/impl/provider.h index 16579ef..ec2e6d5 100644 --- a/lib/webfuse_provider/impl/provider.h +++ b/lib/webfuse_provider/impl/provider.h @@ -3,6 +3,9 @@ #ifndef __cplusplus #include +#include +#else +#include #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 \ No newline at end of file +#endif diff --git a/meson.build b/meson.build index 110a9f6..b7034c7 100644 --- a/meson.build +++ b/meson.build @@ -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 \ No newline at end of file +endif diff --git a/test/webfuse_provider/provider/test_client_protocol.cc b/test/webfuse_provider/provider/test_client_protocol.cc index 6507359..7800a57 100644 --- a/test/webfuse_provider/provider/test_client_protocol.cc +++ b/test/webfuse_provider/provider/test_client_protocol.cc @@ -13,8 +13,10 @@ #include #include +#include #include #include +#include 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 lock(mutex); + recv_queue.push(message); + } + lws_cancel_service(context); + } + + std::string ReceiveMessage() + { + std::lock_guard 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 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(); -} \ No newline at end of file +} diff --git a/test/webfuse_provider/test_util/webfuse_server.cc b/test/webfuse_provider/test_util/webfuse_server.cc index 1b85ac8..fc35155 100644 --- a/test/webfuse_provider/test_util/webfuse_server.cc +++ b/test/webfuse_provider/test_util/webfuse_server.cc @@ -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 response; - { + { std::unique_lock 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()); } -} \ No newline at end of file +} diff --git a/test/webfuse_provider/test_util/ws_server.cc b/test/webfuse_provider/test_util/ws_server.cc index 865a5f8..54f44bd 100644 --- a/test/webfuse_provider/test_util/ws_server.cc +++ b/test/webfuse_provider/test_util/ws_server.cc @@ -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 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 handleMessage_; int port_; bool is_connected; bool is_shutdown_requested; @@ -55,7 +59,6 @@ private: std::thread context; std::mutex mutex; std::queue writeQueue; - std::queue 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 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 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 lock(mutex); - if (wsi == wsi_) + bool handleMessage; { - recvQueue.push(std::string(data, length)); + std::unique_lock lock(mutex); + handleMessage = (wsi == wsi_); } -} -std::string WsServer::Private::ReceiveMessage() -{ - std::unique_lock lock(mutex); - - std::string message; - if (!recvQueue.empty()) + if (handleMessage) { - message = recvQueue.front(); - recvQueue.pop(); + handleMessage_(std::string(data, length)); } - - return message; } std::string WsServer::Private::GetUrl() const @@ -299,4 +295,4 @@ std::string WsServer::Private::GetUrl() const } -} \ No newline at end of file +} diff --git a/test/webfuse_provider/test_util/ws_server.h b/test/webfuse_provider/test_util/ws_server.h index 94a62f2..85dbfe3 100644 --- a/test/webfuse_provider/test_util/ws_server.h +++ b/test/webfuse_provider/test_util/ws_server.h @@ -2,6 +2,7 @@ #define WFP_TEST_UTILS_WS_SERVER_HPP #include +#include 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 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;