mirror of
https://github.com/falk-werner/webfuse
synced 2025-06-13 12:54:15 +00:00
added websockets client and server wrapper
This commit is contained in:
parent
cdb36eaea1
commit
6db99b0634
@ -126,9 +126,12 @@ alltests = executable('alltests',
|
|||||||
'test/webfuse/timer/test_timer.cc',
|
'test/webfuse/timer/test_timer.cc',
|
||||||
'test/webfuse/test_util/tempdir.cc',
|
'test/webfuse/test_util/tempdir.cc',
|
||||||
'test/webfuse/test_util/file_utils.cc',
|
'test/webfuse/test_util/file_utils.cc',
|
||||||
|
'test/webfuse/test_util/server.cc',
|
||||||
'test/webfuse/test_util/ws_server.cc',
|
'test/webfuse/test_util/ws_server.cc',
|
||||||
|
'test/webfuse/test_util/ws_client.cc',
|
||||||
'test/webfuse/test_util/adapter_client.cc',
|
'test/webfuse/test_util/adapter_client.cc',
|
||||||
'test/webfuse/test_util/jansson_test_environment.cc',
|
'test/webfuse/test_util/jansson_test_environment.cc',
|
||||||
|
'test/webfuse/test_util/lws_test_environment.cc',
|
||||||
'test/webfuse/mocks/mock_authenticator.cc',
|
'test/webfuse/mocks/mock_authenticator.cc',
|
||||||
'test/webfuse/mocks/mock_fuse.cc',
|
'test/webfuse/mocks/mock_fuse.cc',
|
||||||
'test/webfuse/mocks/mock_operation_context.cc',
|
'test/webfuse/mocks/mock_operation_context.cc',
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define WF_MOCK_INVOKATION_HANDLER_HPP
|
#define WF_MOCK_INVOKATION_HANDLER_HPP
|
||||||
|
|
||||||
#include "webfuse/test_util/invokation_handler.hpp"
|
#include "webfuse/test_util/invokation_handler.hpp"
|
||||||
#include <gtest/gtest.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
namespace webfuse_test
|
namespace webfuse_test
|
||||||
{
|
{
|
||||||
|
@ -4,9 +4,20 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#include "webfuse/server.h"
|
#include "webfuse/server.h"
|
||||||
#include "webfuse/server_config.h"
|
#include "webfuse/server_config.h"
|
||||||
|
#include "webfuse/test_util/server.hpp"
|
||||||
|
#include "webfuse/test_util/ws_client.hpp"
|
||||||
|
#include "webfuse/mocks/mock_invokation_handler.hpp"
|
||||||
|
#include "webfuse/protocol_names.h"
|
||||||
|
|
||||||
|
using webfuse_test::MockInvokationHander;
|
||||||
|
using webfuse_test::WsClient;
|
||||||
|
using webfuse_test::Server;
|
||||||
|
|
||||||
|
#define TIMEOUT (std::chrono::seconds(10))
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -37,3 +48,14 @@ TEST(server, create_dispose)
|
|||||||
|
|
||||||
rmdir("test");
|
rmdir("test");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(server, connect)
|
||||||
|
{
|
||||||
|
Server server;
|
||||||
|
MockInvokationHander handler;
|
||||||
|
WsClient client(handler, WF_PROTOCOL_NAME_PROVIDER_CLIENT);
|
||||||
|
|
||||||
|
auto future = client.Connect(server.GetPort(), WF_PROTOCOL_NAME_ADAPTER_SERVER);
|
||||||
|
ASSERT_EQ(std::future_status::ready, future.wait_for(TIMEOUT));
|
||||||
|
// future.get();
|
||||||
|
}
|
16
test/webfuse/test_util/lws_test_environment.cc
Normal file
16
test/webfuse/test_util/lws_test_environment.cc
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include "webfuse/impl/util/lws_log.h"
|
||||||
|
|
||||||
|
namespace webfuse_test
|
||||||
|
{
|
||||||
|
|
||||||
|
class LwsTestEnvironment: public testing::Environment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void SetUp()
|
||||||
|
{
|
||||||
|
wf_impl_lwslog_disable();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -1,13 +1,15 @@
|
|||||||
#include "webfuse/tests/integration/server.hpp"
|
#include "webfuse/test_util/server.hpp"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <sstream>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "webfuse/webfuse.h"
|
#include "webfuse/webfuse.h"
|
||||||
#include "webfuse/impl/server.h"
|
#include "webfuse/impl/server.h"
|
||||||
|
#include "webfuse/test_util/tempdir.hpp"
|
||||||
|
|
||||||
#define WF_PATH_MAX (100)
|
#define WF_PATH_MAX (100)
|
||||||
|
|
||||||
@ -50,20 +52,13 @@ class Server::Private
|
|||||||
public:
|
public:
|
||||||
Private()
|
Private()
|
||||||
: is_shutdown_requested(false)
|
: is_shutdown_requested(false)
|
||||||
|
, tempdir("webfuse_test_integration")
|
||||||
{
|
{
|
||||||
snprintf(base_dir, WF_PATH_MAX, "%s", "/tmp/webfuse_test_integration_XXXXXX");
|
|
||||||
char const * result = mkdtemp(base_dir);
|
|
||||||
if (NULL == result)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("unable to create temp dir");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
config = wf_server_config_create();
|
config = wf_server_config_create();
|
||||||
wf_server_config_set_port(config, 0);
|
wf_server_config_set_port(config, 0);
|
||||||
wf_server_config_set_mountpoint_factory(config,
|
wf_server_config_set_mountpoint_factory(config,
|
||||||
&webfuse_test_server_create_mountpoint,
|
&webfuse_test_server_create_mountpoint,
|
||||||
reinterpret_cast<void*>(base_dir));
|
reinterpret_cast<void*>(const_cast<char*>(tempdir.path())));
|
||||||
wf_server_config_set_keypath(config, "server-key.pem");
|
wf_server_config_set_keypath(config, "server-key.pem");
|
||||||
wf_server_config_set_certpath(config, "server-cert.pem");
|
wf_server_config_set_certpath(config, "server-cert.pem");
|
||||||
|
|
||||||
@ -82,26 +77,35 @@ public:
|
|||||||
{
|
{
|
||||||
RequestShutdown();
|
RequestShutdown();
|
||||||
thread.join();
|
thread.join();
|
||||||
rmdir(base_dir);
|
|
||||||
wf_server_dispose(server);
|
wf_server_dispose(server);
|
||||||
wf_server_config_dispose(config);
|
wf_server_config_dispose(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char const * GetBaseDir()
|
||||||
|
{
|
||||||
|
return tempdir.path();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetPort(void) const
|
||||||
|
{
|
||||||
|
return wf_server_get_port(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void Run(Private * context)
|
||||||
|
{
|
||||||
|
while (!context->IsShutdownRequested())
|
||||||
|
{
|
||||||
|
wf_server_service(context->server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool IsShutdownRequested()
|
bool IsShutdownRequested()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(shutdown_lock);
|
std::lock_guard<std::mutex> lock(shutdown_lock);
|
||||||
return is_shutdown_requested;
|
return is_shutdown_requested;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetUrl(void) const
|
|
||||||
{
|
|
||||||
int const port = wf_server_get_port(server);
|
|
||||||
std::ostringstream stream;
|
|
||||||
stream << "wss://localhost:" << port << "/";
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void RequestShutdown()
|
void RequestShutdown()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(shutdown_lock);
|
std::lock_guard<std::mutex> lock(shutdown_lock);
|
||||||
@ -109,22 +113,10 @@ private:
|
|||||||
wf_server_interrupt(server);
|
wf_server_interrupt(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Run(Server::Private * context)
|
|
||||||
{
|
|
||||||
while (!context->IsShutdownRequested())
|
|
||||||
{
|
|
||||||
wf_server_service(context->server);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::mutex shutdown_lock;
|
std::mutex shutdown_lock;
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
bool is_shutdown_requested;
|
bool is_shutdown_requested;
|
||||||
|
TempDir tempdir;
|
||||||
|
|
||||||
public:
|
|
||||||
char base_dir[WF_PATH_MAX];
|
|
||||||
wf_server_config * config;
|
wf_server_config * config;
|
||||||
wf_server * server;
|
wf_server * server;
|
||||||
};
|
};
|
||||||
@ -142,12 +134,12 @@ Server::~Server()
|
|||||||
|
|
||||||
char const * Server::GetBaseDir(void) const
|
char const * Server::GetBaseDir(void) const
|
||||||
{
|
{
|
||||||
return d->base_dir;
|
return d->GetBaseDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Server::GetUrl(void) const
|
int Server::GetPort(void) const
|
||||||
{
|
{
|
||||||
return d->GetUrl();
|
return d->GetPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
|||||||
#ifndef WF_TEST_INTEGRATION_SERVER_HPP
|
#ifndef WF_TEST_INTEGRATION_SERVER_HPP
|
||||||
#define WF_TEST_INTEGRATION_SERVER_HPP
|
#define WF_TEST_INTEGRATION_SERVER_HPP
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace webfuse_test
|
namespace webfuse_test
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -11,10 +9,8 @@ class Server
|
|||||||
public:
|
public:
|
||||||
Server();
|
Server();
|
||||||
~Server();
|
~Server();
|
||||||
void Start(void);
|
|
||||||
void Stop(void);
|
|
||||||
char const * GetBaseDir(void) const;
|
char const * GetBaseDir(void) const;
|
||||||
std::string GetUrl(void) const;
|
int GetPort(void) const;
|
||||||
private:
|
private:
|
||||||
class Private;
|
class Private;
|
||||||
Private * d;
|
Private * d;
|
197
test/webfuse/test_util/ws_client.cc
Normal file
197
test/webfuse/test_util/ws_client.cc
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
#include "webfuse/test_util/ws_client.hpp"
|
||||||
|
#include "webfuse/test_util/invokation_handler.hpp"
|
||||||
|
|
||||||
|
#include <libwebsockets.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
class IServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IServer() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
static int webfuse_test_WsClient_callback(
|
||||||
|
lws * wsi,
|
||||||
|
lws_callback_reasons reason,
|
||||||
|
void * user,
|
||||||
|
void * in,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace webfuse_test
|
||||||
|
{
|
||||||
|
|
||||||
|
class WsClient::Private: public IServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Private(
|
||||||
|
InvokationHandler & handler,
|
||||||
|
std::string const & protocol)
|
||||||
|
: handler_(handler)
|
||||||
|
, protocol_(protocol)
|
||||||
|
, remote_port(0)
|
||||||
|
, remote_use_tls(false)
|
||||||
|
{
|
||||||
|
IServer * self = this;
|
||||||
|
|
||||||
|
memset(protocols, 0, sizeof(lws_protocols) * 2);
|
||||||
|
protocols[0].name = protocol_.c_str();
|
||||||
|
protocols[0].callback = &webfuse_test_WsClient_callback;
|
||||||
|
protocols[0].per_session_data_size = 0;
|
||||||
|
protocols[0].user = self;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(lws_context_creation_info));
|
||||||
|
info.port = CONTEXT_PORT_NO_LISTEN;
|
||||||
|
info.protocols = protocols;
|
||||||
|
info.uid = -1;
|
||||||
|
info.gid = -1;
|
||||||
|
info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
|
||||||
|
|
||||||
|
context = lws_create_context(&info);
|
||||||
|
|
||||||
|
lws_vhost * vhost = lws_create_vhost(context, & info);
|
||||||
|
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||||
|
info.client_ssl_cert_filepath = "client-cert.pem";
|
||||||
|
info.client_ssl_private_key_filepath = "client-key.pem";
|
||||||
|
info.client_ssl_ca_filepath = "server-cert.pem";
|
||||||
|
lws_init_vhost_client_ssl(&info, vhost);
|
||||||
|
|
||||||
|
thread = std::thread(&Run, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Private()
|
||||||
|
{
|
||||||
|
Invoke(command::shutdown);
|
||||||
|
lws_cancel_service(context);
|
||||||
|
|
||||||
|
thread.join();
|
||||||
|
lws_context_destroy(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<void> Connect(int port, std::string const & protocol, bool use_tls)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
remote_port = port;
|
||||||
|
remote_protocol = protocol;
|
||||||
|
remote_use_tls = use_tls;
|
||||||
|
commands.push(command::connect);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::promise<void> p;
|
||||||
|
p.set_exception(std::make_exception_ptr(std::runtime_error("not implemented")));
|
||||||
|
return p.get_future();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<std::string> Invoke(std::string const & message)
|
||||||
|
{
|
||||||
|
std::promise<std::string> p;
|
||||||
|
p.set_exception(std::make_exception_ptr(std::runtime_error("not implemented")));
|
||||||
|
return p.get_future();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class command
|
||||||
|
{
|
||||||
|
run,
|
||||||
|
shutdown,
|
||||||
|
connect
|
||||||
|
};
|
||||||
|
|
||||||
|
static void Run(Private * self)
|
||||||
|
{
|
||||||
|
bool is_running = true;
|
||||||
|
|
||||||
|
while (is_running)
|
||||||
|
{
|
||||||
|
switch (self->GetCommand())
|
||||||
|
{
|
||||||
|
case command::run:
|
||||||
|
lws_service(self->context, 0);
|
||||||
|
break;
|
||||||
|
case command::shutdown:
|
||||||
|
is_running = false;
|
||||||
|
break;
|
||||||
|
case command::connect:
|
||||||
|
// ToDo: connect
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command GetCommand()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
command command = command::run;
|
||||||
|
if (!commands.empty())
|
||||||
|
{
|
||||||
|
command = commands.front();
|
||||||
|
commands.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Invoke(command command)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
commands.push(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
InvokationHandler & handler_;
|
||||||
|
std::string protocol_;
|
||||||
|
lws_context_creation_info info;
|
||||||
|
lws_protocols protocols[2];
|
||||||
|
lws_context * context;
|
||||||
|
std::thread thread;
|
||||||
|
std::mutex mutex;
|
||||||
|
std::queue<command> commands;
|
||||||
|
int remote_port;
|
||||||
|
std::string remote_protocol;
|
||||||
|
bool remote_use_tls;
|
||||||
|
};
|
||||||
|
|
||||||
|
WsClient::WsClient(
|
||||||
|
InvokationHandler& handler,
|
||||||
|
std::string const & protocol)
|
||||||
|
: d(new Private(handler, protocol))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
WsClient::~WsClient()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<void> WsClient::Connect(int port, std::string const & protocol, bool use_tls)
|
||||||
|
{
|
||||||
|
return d->Connect(port, protocol, use_tls);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<std::string> WsClient::Invoke(std::string const & message)
|
||||||
|
{
|
||||||
|
return d->Invoke(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
30
test/webfuse/test_util/ws_client.hpp
Normal file
30
test/webfuse/test_util/ws_client.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef WF_TEST_UTIL_WS_CLIENT_HPP
|
||||||
|
#define WF_TEST_UTIL_WS_CLIENT_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
namespace webfuse_test
|
||||||
|
{
|
||||||
|
|
||||||
|
class InvokationHandler;
|
||||||
|
|
||||||
|
class WsClient
|
||||||
|
{
|
||||||
|
WsClient(WsClient const &) = delete;
|
||||||
|
WsClient & operator=(WsClient const &) = delete;
|
||||||
|
public:
|
||||||
|
WsClient(
|
||||||
|
InvokationHandler& handler,
|
||||||
|
std::string const & protocol);
|
||||||
|
virtual ~WsClient();
|
||||||
|
std::future<void> Connect(int port, std::string const & protocol, bool use_tls = true);
|
||||||
|
std::future<std::string> Invoke(std::string const & message);
|
||||||
|
private:
|
||||||
|
class Private;
|
||||||
|
Private *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -143,7 +143,6 @@ WsServer::Private::Private(
|
|||||||
, is_shutdown_requested(false)
|
, is_shutdown_requested(false)
|
||||||
, wsi_(nullptr)
|
, wsi_(nullptr)
|
||||||
{
|
{
|
||||||
wf_impl_lwslog_disable();
|
|
||||||
IServer * server = this;
|
IServer * server = this;
|
||||||
memset(ws_protocols, 0, sizeof(struct lws_protocols) * 2 );
|
memset(ws_protocols, 0, sizeof(struct lws_protocols) * 2 );
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user