1
0
mirror of https://github.com/falk-werner/webfuse synced 2024-10-27 20:34:10 +00:00

added implementation of wf_client_authenticate

This commit is contained in:
Falk Werner 2020-06-12 20:38:20 +02:00
parent 021e056960
commit adaec875d9
4 changed files with 208 additions and 1 deletions

View File

@ -114,7 +114,7 @@ void
wf_impl_client_authenticate(
struct wf_client * client)
{
wf_impl_client_protocol_callback(&client->protocol, WF_CLIENT_AUTHENTICATION_FAILED, NULL);
wf_impl_client_protocol_authenticate(&client->protocol);
}
void

View File

@ -1,12 +1,73 @@
#include "webfuse/adapter/impl/client_protocol.h"
#include "webfuse/adapter/client_callback.h"
#include "webfuse/adapter/impl/credentials.h"
#include "webfuse/core/protocol_names.h"
#include "webfuse/core/url.h"
#include "webfuse/core/util.h"
#include "webfuse/core/timer/manager.h"
#include "webfuse/core/jsonrpc/response.h"
#include "webfuse/core/jsonrpc/proxy.h"
#include "webfuse/core/message.h"
#include "webfuse/core/message_queue.h"
#include "webfuse/core/container_of.h"
#include <stddef.h>
#include <libwebsockets.h>
#define WF_DEFAULT_TIMEOUT (10 * 1000)
static void
wf_impl_client_protocol_process(
struct wf_client_protocol * protocol,
char const * data,
size_t length)
{
json_t * message = json_loadb(data, length, 0, NULL);
if (NULL != message)
{
if (wf_jsonrpc_is_response(message))
{
wf_jsonrpc_proxy_onresult(protocol->proxy, message);
}
json_decref(message);
}
}
static bool
wf_impl_client_protocol_send(
json_t * request,
void * user_data)
{
bool result = false;
struct wf_client_protocol * protocol = user_data;
struct wf_message * message = wf_message_create(request);
if (NULL != message)
{
wf_slist_append(&protocol->messages, &message->item);
lws_callback_on_writable(protocol->wsi);
result = true;
}
return result;
}
static void
wf_impl_client_protocol_on_authenticate_finished(
void * user_data,
json_t const * result,
json_t const * WF_UNUSED_PARAM(error))
{
struct wf_client_protocol * protocol = user_data;
int const reason = (NULL != result) ? WF_CLIENT_AUTHENTICATED : WF_CLIENT_AUTHENTICATION_FAILED;
protocol->callback(protocol->user_data, reason, NULL);
}
static int wf_impl_client_protocol_lws_callback(
struct lws * wsi,
enum lws_callback_reasons reason,
@ -20,6 +81,8 @@ static int wf_impl_client_protocol_lws_callback(
if (NULL != protocol)
{
wf_timer_manager_check(protocol->timer_manager);
switch (reason)
{
case LWS_CALLBACK_CLIENT_ESTABLISHED:
@ -35,6 +98,8 @@ static int wf_impl_client_protocol_lws_callback(
protocol->callback(protocol->user_data, WF_CLIENT_DISCONNECTED, NULL);
protocol->wsi = NULL;
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
wf_impl_client_protocol_process(protocol, in, len);
case LWS_CALLBACK_SERVER_WRITEABLE:
// fall-through
case LWS_CALLBACK_CLIENT_WRITEABLE:
@ -44,6 +109,18 @@ static int wf_impl_client_protocol_lws_callback(
{
result = 1;
}
else if (!wf_slist_empty(&protocol->messages))
{
struct wf_slist_item * item = wf_slist_remove_first(&protocol->messages);
struct wf_message * message = wf_container_of(item, struct wf_message, item);
lws_write(wsi, (unsigned char*) message->data, message->length, LWS_WRITE_TEXT);
wf_message_dispose(message);
if (!wf_slist_empty(&protocol->messages))
{
lws_callback_on_writable(wsi);
}
}
}
default:
break;
@ -65,6 +142,11 @@ wf_impl_client_protocol_init(
protocol->callback = callback;
protocol->user_data = user_data;
protocol->callback(protocol->user_data, WF_CLIENT_INIT, NULL);
wf_slist_init(&protocol->messages);
protocol->timer_manager = wf_timer_manager_create();
protocol->proxy = wf_jsonrpc_proxy_create(protocol->timer_manager, WF_DEFAULT_TIMEOUT, &wf_impl_client_protocol_send, protocol);
}
void
@ -72,6 +154,9 @@ wf_impl_client_protocol_cleanup(
struct wf_client_protocol * protocol)
{
protocol->callback(protocol->user_data, WF_CLIENT_CLEANUP, NULL);
wf_jsonrpc_proxy_dispose(protocol->proxy);
wf_timer_manager_dispose(protocol->timer_manager);
wf_message_queue_cleanup(&protocol->messages);
}
void
@ -141,3 +226,23 @@ wf_impl_client_protocol_disconnect(
}
}
void
wf_impl_client_protocol_authenticate(
struct wf_client_protocol * protocol)
{
struct wf_credentials creds;
wf_impl_credentials_init_default(&creds);
protocol->callback(protocol->user_data, WF_CLIENT_AUTHENTICATE_GET_CREDENTIALS, &creds);
json_incref(creds.data);
wf_jsonrpc_proxy_invoke(
protocol->proxy,
&wf_impl_client_protocol_on_authenticate_finished,
protocol,
"authenticate",
"sj",
creds.type, creds.data);
wf_impl_credentials_cleanup(&creds);
}

View File

@ -2,6 +2,7 @@
#define WF_ADAPTER_IMPL_CLIENT_PROTOCOL_H
#include "webfuse/adapter/client_callback.h"
#include "webfuse/core/slist.h"
#ifndef __cplusplus
#include <stdbool.h>
@ -15,6 +16,9 @@ extern "C"
struct lws_protocols;
struct lws_context;
struct wf_jsonrpc_proxy;
struct wf_timer_manager;
typedef void
wf_client_protocol_callback_fn(
void * user_data,
@ -28,6 +32,9 @@ struct wf_client_protocol
struct lws * wsi;
wf_client_callback_fn * callback;
void * user_data;
struct wf_timer_manager * timer_manager;
struct wf_jsonrpc_proxy * proxy;
struct wf_slist messages;
};
extern void
@ -61,6 +68,10 @@ extern void
wf_impl_client_protocol_disconnect(
struct wf_client_protocol * protocol);
extern void
wf_impl_client_protocol_authenticate(
struct wf_client_protocol * protocol);
#ifdef __cplusplus
}
#endif

View File

@ -3,6 +3,7 @@
#include "webfuse/adapter/client.h"
#include "webfuse/adapter/credentials.h"
#include "webfuse/adapter/credentials.h"
#include "webfuse/core/protocol_names.h"
#include "webfuse/utils/ws_server.h"
#include "webfuse/mocks/mock_adapter_client_callback.hpp"
@ -12,12 +13,21 @@ using webfuse_test::WsServer;
using webfuse_test::MockAdapterClientCallback;
using webfuse_test::TimeoutWatcher;
using testing::_;
using testing::Invoke;
#define TIMEOUT (std::chrono::milliseconds(10 * 1000))
namespace
{
void GetCredentials(wf_client *, int, void * arg)
{
auto * creds = reinterpret_cast<wf_credentials*>(arg);
wf_credentials_set_type(creds, "username");
wf_credentials_add(creds, "username", "Bob");
wf_credentials_add(creds, "password", "secret");
}
enum class connection_state
{
disconnected,
@ -143,3 +153,84 @@ TEST(AdapterClient, Connect)
wf_client_dispose(client);
}
TEST(AdapterClient, Authenticate)
{
TimeoutWatcher watcher(TIMEOUT);
WsServer server(WF_PROTOCOL_NAME_PROVIDER_SERVER);
MockAdapterClientCallback callback;
EXPECT_CALL(callback, Invoke(_, WF_CLIENT_INIT, nullptr)).Times(1);
EXPECT_CALL(callback, Invoke(_, WF_CLIENT_CREATED, nullptr)).Times(1);
EXPECT_CALL(callback, Invoke(_, WF_CLIENT_GET_TLS_CONFIG, _)).Times(1);
EXPECT_CALL(callback, Invoke(_, WF_CLIENT_CLEANUP, nullptr)).Times(1);
EXPECT_CALL(callback, Invoke(_, WF_CLIENT_CONNECTED, nullptr)).Times(1);
EXPECT_CALL(callback, Invoke(_, WF_CLIENT_DISCONNECTED, nullptr)).Times(1);
EXPECT_CALL(callback, Invoke(_, WF_CLIENT_AUTHENTICATE_GET_CREDENTIALS, _)).Times(1)
.WillOnce(Invoke(GetCredentials));
bool called = false;
bool * p_called = &called;
EXPECT_CALL(callback, Invoke(_, WF_CLIENT_AUTHENTICATED, nullptr)).Times(1)
.WillOnce(Invoke([p_called] (wf_client *, int, void *) {
*p_called = true;
}));
wf_client * client = wf_client_create(
callback.GetCallbackFn(), callback.GetUserData());
wf_client_connect(client, server.GetUrl().c_str());
while (!server.IsConnected())
{
watcher.check();
wf_client_service(client);
}
wf_client_authenticate(client);
json_t * request = server.ReceiveMessage();
while (nullptr == request)
{
watcher.check();
wf_client_service(client);
request = server.ReceiveMessage();
}
json_t * id = json_object_get(request, "id");
ASSERT_TRUE(json_is_integer(id));
json_t * method = json_object_get(request, "method");
ASSERT_TRUE(json_is_string(method));
ASSERT_STREQ("authenticate", json_string_value(method));
json_t * params = json_object_get(request, "params");
ASSERT_TRUE(json_is_array(params));
ASSERT_EQ(2, json_array_size(params));
json_t * type = json_array_get(params, 0);
ASSERT_TRUE(json_is_string(type));
json_t * creds = json_array_get(params, 1);
ASSERT_TRUE(json_is_object(creds));
json_t * username = json_object_get(creds, "username");
ASSERT_TRUE(json_is_string(username));
ASSERT_STREQ("Bob", json_string_value(username));
json_t * password = json_object_get(creds, "password");
ASSERT_TRUE(json_is_string(password));
ASSERT_STREQ("secret", json_string_value(password));
json_t * response = json_object();
json_object_set(response, "id", id);
json_object_set_new(response, "result", json_object());
server.SendMessage(response);
json_decref(request);
while (!called) {
watcher.check();
wf_client_service(client);
}
wf_client_disconnect(client);
while (server.IsConnected())
{
watcher.check();
wf_client_service(client);
}
wf_client_dispose(client);
}