added websockets client and server wrapper

pull/79/head
Falk Werner 4 years ago
parent cdb36eaea1
commit 6db99b0634

@ -126,9 +126,12 @@ alltests = executable('alltests',
'test/webfuse/timer/test_timer.cc',
'test/webfuse/test_util/tempdir.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_client.cc',
'test/webfuse/test_util/adapter_client.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_fuse.cc',
'test/webfuse/mocks/mock_operation_context.cc',

@ -2,7 +2,7 @@
#define WF_MOCK_INVOKATION_HANDLER_HPP
#include "webfuse/test_util/invokation_handler.hpp"
#include <gtest/gtest.h>
#include <gmock/gmock.h>
namespace webfuse_test
{

@ -4,9 +4,20 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <chrono>
#include "webfuse/server.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
{
@ -36,4 +47,15 @@ TEST(server, create_dispose)
wf_server_config_dispose(config);
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();
}

@ -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 <mutex>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/stat.h>
#include <string>
#include "webfuse/webfuse.h"
#include "webfuse/impl/server.h"
#include "webfuse/test_util/tempdir.hpp"
#define WF_PATH_MAX (100)
@ -50,20 +52,13 @@ class Server::Private
public:
Private()
: 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();
wf_server_config_set_port(config, 0);
wf_server_config_set_mountpoint_factory(config,
&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_certpath(config, "server-cert.pem");
@ -82,34 +77,22 @@ public:
{
RequestShutdown();
thread.join();
rmdir(base_dir);
wf_server_dispose(server);
wf_server_config_dispose(config);
}
bool IsShutdownRequested()
char const * GetBaseDir()
{
std::lock_guard<std::mutex> lock(shutdown_lock);
return is_shutdown_requested;
return tempdir.path();
}
std::string GetUrl(void) const
int GetPort(void) const
{
int const port = wf_server_get_port(server);
std::ostringstream stream;
stream << "wss://localhost:" << port << "/";
return stream.str();
return wf_server_get_port(server);
}
private:
void RequestShutdown()
{
std::lock_guard<std::mutex> lock(shutdown_lock);
is_shutdown_requested = true;
wf_server_interrupt(server);
}
static void Run(Server::Private * context)
static void Run(Private * context)
{
while (!context->IsShutdownRequested())
{
@ -117,14 +100,23 @@ private:
}
}
bool IsShutdownRequested()
{
std::lock_guard<std::mutex> lock(shutdown_lock);
return is_shutdown_requested;
}
void RequestShutdown()
{
std::lock_guard<std::mutex> lock(shutdown_lock);
is_shutdown_requested = true;
wf_server_interrupt(server);
}
std::mutex shutdown_lock;
std::thread thread;
bool is_shutdown_requested;
public:
char base_dir[WF_PATH_MAX];
TempDir tempdir;
wf_server_config * config;
wf_server * server;
};
@ -142,12 +134,12 @@ Server::~Server()
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
#define WF_TEST_INTEGRATION_SERVER_HPP
#include <string>
namespace webfuse_test
{
@ -11,10 +9,8 @@ class Server
public:
Server();
~Server();
void Start(void);
void Stop(void);
char const * GetBaseDir(void) const;
std::string GetUrl(void) const;
int GetPort(void) const;
private:
class Private;
Private * d;

@ -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);
}
}

@ -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)
, wsi_(nullptr)
{
wf_impl_lwslog_disable();
IServer * server = this;
memset(ws_protocols, 0, sizeof(struct lws_protocols) * 2 );

Loading…
Cancel
Save