feat(authentication): provide an authentication mechanism (#19)

* moves server into session

* renames jsonrpc server to jsonrpc proxy

* moves server into session

* renames jsonrpc server to jsonrpc proxy

* adds json rpc server

* removes obsolete proxy from protocol

* changes interface of jsonrpc_proxy_onresult to accept previously parsed messages

* adds infrastructure to process incoming requests; fixes invalid read of ill formatted responses

* adds description of authentication request

* adds authentication request

* adds userdb for authentication purposes

* removes debug code: console.log()

* fixes cmake build error (missing openssl symbols)

* fixes typo

* replaces ASCII art by UML diagram

* renames BAD_NOACCESS to BAD_ACCESS_DENIED

* fixes style

* adds docu of authentication

* ignored false positives of flawfinder

* fixes style issues

* fixes javascript style issues
pull/27/head
Falk Werner 6 years ago committed by nosamad
parent 1d413456a2
commit 87f34fa768

@ -74,6 +74,7 @@ add_library(webfuse-adapter-static STATIC
lib/webfuse/adapter/impl/authenticator.c lib/webfuse/adapter/impl/authenticator.c
lib/webfuse/adapter/impl/authenticators.c lib/webfuse/adapter/impl/authenticators.c
lib/webfuse/adapter/impl/credentials.c lib/webfuse/adapter/impl/credentials.c
lib/webfuse/adapter/impl/operations.c
lib/webfuse/adapter/impl/time/timepoint.c lib/webfuse/adapter/impl/time/timepoint.c
lib/webfuse/adapter/impl/time/timer.c lib/webfuse/adapter/impl/time/timer.c
lib/webfuse/adapter/impl/time/timeout_manager.c lib/webfuse/adapter/impl/time/timeout_manager.c
@ -83,6 +84,7 @@ add_library(webfuse-adapter-static STATIC
lib/webfuse/adapter/impl/operation/open.c lib/webfuse/adapter/impl/operation/open.c
lib/webfuse/adapter/impl/operation/close.c lib/webfuse/adapter/impl/operation/close.c
lib/webfuse/adapter/impl/operation/read.c lib/webfuse/adapter/impl/operation/read.c
lib/webfuse/adapter/impl/jsonrpc/proxy.c
lib/webfuse/adapter/impl/jsonrpc/server.c lib/webfuse/adapter/impl/jsonrpc/server.c
lib/webfuse/adapter/impl/jsonrpc/method.c lib/webfuse/adapter/impl/jsonrpc/method.c
lib/webfuse/adapter/impl/jsonrpc/request.c lib/webfuse/adapter/impl/jsonrpc/request.c
@ -185,6 +187,8 @@ install(FILES "${PROJECT_BINARY_DIR}/libwebfuse-provider.pc" DESTINATION lib${LI
# examples # examples
pkg_check_modules(OPENSSL REQUIRED openssl)
if(NOT WITHOUT_EXAMPLE) if(NOT WITHOUT_EXAMPLE)
# libuserdb # libuserdb
@ -211,9 +215,9 @@ add_executable(webfused
example/daemon/main.c example/daemon/main.c
) )
target_link_libraries(webfused PUBLIC webfuse-adapter ${EXTRA_LIBS}) target_link_libraries(webfused PUBLIC webfuse-adapter userdb ${OPENSSL_LIBRARIES} ${EXTRA_LIBS})
target_include_directories(webfused PUBLIC ${EXTRA_INCLUDE_DIRS}) target_include_directories(webfused PUBLIC ${EXTRA_INCLUDE_DIRS})
target_compile_options(webfused PUBLIC ${EXTRA_CFLAGS}) target_compile_options(webfused PUBLIC ${C_WARNINGS} ${OPENSSL_CFLAGS_OTHER} ${EXTRA_CFLAGS})
# provider # provider
@ -229,9 +233,6 @@ target_compile_options(webfuse-provider-app PUBLIC ${EXTRA_CFLAGS})
# webfuse-passwd # webfuse-passwd
pkg_check_modules(OPENSSL REQUIRED openssl)
add_executable(webfuse-passwd add_executable(webfuse-passwd
example/passwd/main.c example/passwd/main.c
) )

@ -31,36 +31,9 @@ To avoid Steps 1 and 2, it would be great to keep the update file entirely in we
webfuse solves this problem by using the [WebSocket](https://en.wikipedia.org/wiki/WebSocket) protocol. The emdedded device runs a service, known as webfuse adapter, awaiting incoming connections, e.g. from a web browser. The browser acts as a file system provider, providing the update file to the device. webfuse solves this problem by using the [WebSocket](https://en.wikipedia.org/wiki/WebSocket) protocol. The emdedded device runs a service, known as webfuse adapter, awaiting incoming connections, e.g. from a web browser. The browser acts as a file system provider, providing the update file to the device.
## Concecpt ## Concept
+---------------------+ +-------------+ +------+ ![concept](doc/concept.png)
| Filesystem Provider | | webfuse | | user |
| (e.g. Webbrowser) | | daemon | | |
+----------+----------+ +------+------+ +---+--+
| | |
| +-+-+ |
| | +--+ |
| | | | fuse_mount |
| | +<-+ |
| | | |
| | +--+ |
| | | | start ws |
| | +<-+ |
| +-+-+ |
| | |
+-+-+ connect +-+-+ |
| |--------------->| | |
+-+-+ +-+-+ |
| | |
| +-+-+ ls +-+-+
+-+-+ readdir | |<------------+ |
| |<---------------+ | | |
| | | | | |
| | readdir_resp | | | |
| +--------------->| | [., ..] | |
+-+-+ | +------------>| |
| +-+-+ +-+-+
| | |
With webfuse it is possible to implement remote filesystems based on websockets. With webfuse it is possible to implement remote filesystems based on websockets.
A reference implementation of such a daemon is provided within the examples. The picture above describes the workflow: A reference implementation of such a daemon is provided within the examples. The picture above describes the workflow:
@ -146,7 +119,7 @@ A response is used to answer a prior request. There are two kinds of responses:
| BAD_BUSY | 4 | resource busy | | BAD_BUSY | 4 | resource busy |
| BAD_FORMAT | 5 | invalid formt | | BAD_FORMAT | 5 | invalid formt |
| BAD_NOENTRY | 101 | invalid entry | | BAD_NOENTRY | 101 | invalid entry |
| BAD_NOACCESS | 102 | access not allowed | | BAD_ACCESS_DENIED | 102 | access not allowed |
#### Notification #### Notification
@ -162,7 +135,7 @@ Notfications are used to inform a receiver about something. Unlike requests, not
| method_name | string | name of the method to invoke | | method_name | string | name of the method to invoke |
| params | array | method specific parameters | | params | array | method specific parameters |
### Requests ### Requests (Adapter -> Provider)
#### lookup #### lookup
@ -300,6 +273,73 @@ Read from an open file.
| "identiy" | Use data as is; note that JSON strings are UTF-8 encoded | | "identiy" | Use data as is; note that JSON strings are UTF-8 encoded |
| "base64" | data is base64 encoded | | "base64" | data is base64 encoded |
### Requests (Provider -> Adapter)
#### authtenticate
Authenticate the provider.
If authentication is enabled, a provider must be authenticated by the adapter before the adapter will send any messages.
fs provider: {"method": "authenticate", "params": [<type>, <credentials>], "id": <id>}
webfuse daemon: {"result": {}, "id": <id>}
| Item | Data type | Description |
| ----------- | ----------| ------------------------------- |
| type | string | authentication type (see below) |
| credentials | object | credentials to authenticate |
##### authentication types
- **username**: authenticate via username and password
`{"username": <username>, "password": <password>}`
## Authentication
By default, webfuse daemon will redirect each filesystem call to the first connected provider without any authentication.
This might be good for testing purposes or when an external authentication mechanism is used. In some use cases, explicit authentication is needed. Therefore, authentication can be enabled within webfuse daemon.
When authentication is enabled, filesystem calls are only redirected to a connected provider, after `authenticate`
has succeeded.
![authenticate](doc/authenticate.png)
### Enable authentication
Authentication is enabled, if one or more authenticators are registered via `wf_server_config`.
static bool authenticate(struct wf_credentials * creds, void * user_data)
{
char const * username = wf_credentials_get(creds, "username");
char const * password = wf_credentials_get(creds, "password");
return ((NULL != username) && (0 == strcmp(username, "bob")) &&
(NULL != password) && (0 == strcmp(password, "???")));
}
wf_server_config * config = wf_server_config_create();
wf_server_config_add_authenticator(config, "username", &authenticate, NULL);
wf_server * server = wf_server_create(config);
//...
### Authenticator types and credentidals
Each authenticator is identified by a user defined string, called `type`. The type is provided by the `authenticate` request, so you can define different authenticators for different authentication types, e.g. username, certificate, token.
Actually, only one type is used: **username**
**It is strongly recommended to prefix custom authenticator types with an underscore (`_`) to avoid name clashes.**
The `wf_credentials`struct represents a map to access credentials as key-value pairs, where both, key and value, are of type string.
#### username
The authenticator type **username** is used to authenticate via username and password. Valid credentials should contain two keys.
- **username** refers to the name of the user
- **password** refers to the password of the user
**Note** that no further encryption is done, so this authenticator type should not be used over unencrypted websocket connections.
## Build and run ## Build and run
To install dependencies, see below. To install dependencies, see below.

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

@ -0,0 +1,28 @@
@startuml
participant "Filesystem Provider\n(e.g. Webbrowser)" as provider
participant "webfuse\ndaemon" as daemon
actor "user" as user
group directory listing fails without authentication
user -> daemon : ls
daemon -> daemon : is_authenticated
daemon -->x user : error: no entry
end
group authenticate
provider -> daemon: authenticate(type, credentials)
daemon -> daemon: get_authenticator(type)
daemon -> daemon: check(credentials)
daemon --> provider: result
end
group directory listing succeeds after authentication
user -> daemon : ls
daemon -> daemon : is_authenticated
daemon -> provider : readdir
provider --> daemon : readdir_resp
daemon --> user : [., ..]
end
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

@ -0,0 +1,30 @@
@startuml
participant "Filesystem Provider\n(e.g. Webbrowser)" as provider
participant "webfuse\ndaemon" as daemon
actor "user" as user
group startup
daemon -> daemon : fuse_mount
daemon -> daemon : start ws
end
...
group connect
provider -> daemon : connect
opt authentication
provider -> daemon: authenticate
daemon -> daemon: check credentials
daemon --> provider: okay
end
end
...
group directory listing
user -> daemon : ls
daemon -> provider : readdir
provider --> daemon : readdir_resp
daemon --> user : [., ..]
end
...
@enduml

@ -7,9 +7,9 @@
#include <unistd.h> #include <unistd.h>
#include <getopt.h> #include <getopt.h>
#include <jansson.h>
#include <webfuse_adapter.h> #include <webfuse_adapter.h>
#include <userdb.h>
struct args struct args
@ -50,20 +50,12 @@ static bool authenticate(struct wf_credentials * creds, void * user_data)
char const * password = wf_credentials_get(creds, "password"); char const * password = wf_credentials_get(creds, "password");
if ((NULL != username) && (NULL != password)) if ((NULL != username) && (NULL != password))
{ {
json_t * passwd = json_load_file(args->passwd_path, 0, NULL); struct userdb * db = userdb_create("<pepper>");
if (NULL != passwd) result = userdb_load(db, args->passwd_path);
if (result)
{ {
json_t * user = json_object_get(passwd, username); result = userdb_check(db, username, password);
if (json_is_object(user)) userdb_dispose(db);
{
json_t * password_holder = json_object_get(user, "password");
if (json_is_string(password_holder))
{
result = (0 == strcmp(password, json_string_value(password_holder)));
}
}
json_decref(passwd);
} }
} }

@ -6,20 +6,51 @@ export class ConnectionView {
this.element = document.createElement("div"); this.element = document.createElement("div");
const connectBox = document.createElement("div");
this.element.appendChild(connectBox);
const urlLabel = document.createElement("span"); const urlLabel = document.createElement("span");
urlLabel.textContent = "URL:"; urlLabel.textContent = "URL:";
this.element.appendChild(urlLabel); connectBox.appendChild(urlLabel);
this.urlTextbox = document.createElement("input"); this.urlTextbox = document.createElement("input");
this.urlTextbox.type = "text"; this.urlTextbox.type = "text";
this.urlTextbox.value = window.location.href.replace(/^http/, "ws"); this.urlTextbox.value = window.location.href.replace(/^http/, "ws");
this.element.appendChild(this.urlTextbox); connectBox.appendChild(this.urlTextbox);
this.connectButton = document.createElement("input"); this.connectButton = document.createElement("input");
this.connectButton.type = "button"; this.connectButton.type = "button";
this.connectButton.value = "connect"; this.connectButton.value = "connect";
this.connectButton.addEventListener("click", () => { this._onConnectButtonClicked(); }); this.connectButton.addEventListener("click", () => { this._onConnectButtonClicked(); });
this.element.appendChild(this.connectButton); connectBox.appendChild(this.connectButton);
const authenticateBox = document.createElement("div");
this.element.appendChild(authenticateBox);
const usernameLabel = document.createElement("span");
usernameLabel.textContent = "user:";
authenticateBox.appendChild(usernameLabel);
this.usernameTextbox = document.createElement("input");
this.usernameTextbox.type = "text";
this.usernameTextbox.value = "bob";
authenticateBox.appendChild(this.usernameTextbox);
const passwordLabel = document.createElement("span");
passwordLabel.textContent = "user:";
authenticateBox.appendChild(passwordLabel);
this.passwordTextbox = document.createElement("input");
this.passwordTextbox.type = "password";
this.passwordTextbox.value = "secret";
authenticateBox.appendChild(this.passwordTextbox);
this.authenticateButton = document.createElement("input");
this.authenticateButton.type = "button";
this.authenticateButton.value = "authenticate";
this.authenticateButton.addEventListener("click", () => { this._onAuthenticateButtonClicked(); });
authenticateBox.appendChild(this.authenticateButton);
} }
_onConnectButtonClicked() { _onConnectButtonClicked() {
@ -32,6 +63,15 @@ export class ConnectionView {
} }
} }
_onAuthenticateButtonClicked() {
if (this._client.isConnected()) {
const username = this.usernameTextbox.value;
const password = this.passwordTextbox.value;
this._client.authenticate("username", { username, password });
}
}
_onConnectionOpened() { _onConnectionOpened() {
this.connectButton.value = "disconnect"; this.connectButton.value = "disconnect";
} }

@ -24,6 +24,16 @@ export class Client {
}; };
} }
authenticate(type, credentials) {
const request = {
"method": "authenticate",
"params": [type, credentials],
"id": 42
};
this._ws.send(JSON.stringify(request));
}
disconnect() { disconnect() {
if (this._ws) { if (this._ws) {
this._ws.close(); this._ws.close();

@ -127,9 +127,9 @@ static char * compute_hash(
{ {
EVP_MD_CTX * context = EVP_MD_CTX_new(); EVP_MD_CTX * context = EVP_MD_CTX_new();
EVP_DigestInit_ex(context, digest, NULL); EVP_DigestInit_ex(context, digest, NULL);
EVP_DigestUpdate(context, password, strlen(password)); EVP_DigestUpdate(context, password, strlen(password)); /* Flawfinder: ignore */
EVP_DigestUpdate(context, salt, strlen(salt)); EVP_DigestUpdate(context, salt, strlen(salt)); /* Flawfinder: ignore */
EVP_DigestUpdate(context, db->pepper, strlen(db->pepper)); EVP_DigestUpdate(context, db->pepper, strlen(db->pepper)); /* Flawfinder: ignore */
EVP_DigestFinal_ex(context, hash, &hash_size); EVP_DigestFinal_ex(context, hash, &hash_size);
EVP_MD_CTX_free(context); EVP_MD_CTX_free(context);

@ -268,7 +268,7 @@ static void fs_open(
} }
else else
{ {
wfp_respond_error(request, WF_BAD_NOACCESS); wfp_respond_error(request, WF_BAD_ACCESS_DENIED);
} }
} }
else else

@ -10,7 +10,7 @@
#define WF_BAD_FORMAT 5 #define WF_BAD_FORMAT 5
#define WF_BAD_NOENTRY 101 #define WF_BAD_NOENTRY 101
#define WF_BAD_NOACCESS 102 #define WF_BAD_ACCESS_DENIED 102
typedef int wf_status; typedef int wf_status;

@ -1,7 +1,7 @@
#include "webfuse/adapter/impl/filesystem.h" #include "webfuse/adapter/impl/filesystem.h"
#include "webfuse/adapter/impl/operations.h" #include "webfuse/adapter/impl/operations.h"
#include "webfuse/adapter/impl/jsonrpc/server.h"
#include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
@ -19,7 +19,7 @@ static struct fuse_lowlevel_ops const filesystem_operations =
bool wf_impl_filesystem_init( bool wf_impl_filesystem_init(
struct wf_impl_filesystem * filesystem, struct wf_impl_filesystem * filesystem,
struct wf_impl_jsonrpc_server * rpc, struct wf_impl_session_manager * session_manager,
char * mount_point) char * mount_point)
{ {
bool result = false; bool result = false;
@ -29,7 +29,7 @@ bool wf_impl_filesystem_init(
filesystem->args.argv = argv; filesystem->args.argv = argv;
filesystem->args.allocated = 0; filesystem->args.allocated = 0;
filesystem->user_data.rpc = rpc; filesystem->user_data.session_manager = session_manager;
filesystem->user_data.timeout = 1.0; filesystem->user_data.timeout = 1.0;
memset(&filesystem->buffer, 0, sizeof(struct fuse_buf)); memset(&filesystem->buffer, 0, sizeof(struct fuse_buf));

@ -13,7 +13,7 @@ extern "C"
{ {
#endif #endif
struct wf_impl_jsonrpc_server; struct wf_impl_session_manager;
struct wf_impl_filesystem struct wf_impl_filesystem
{ {
@ -25,7 +25,7 @@ struct wf_impl_filesystem
extern bool wf_impl_filesystem_init( extern bool wf_impl_filesystem_init(
struct wf_impl_filesystem * filesystem, struct wf_impl_filesystem * filesystem,
struct wf_impl_jsonrpc_server * rpc, struct wf_impl_session_manager * session_manager,
char * mount_point); char * mount_point);
extern void wf_impl_filesystem_cleanup( extern void wf_impl_filesystem_cleanup(

@ -1,10 +1,9 @@
#include "webfuse/adapter/impl/jsonrpc/method_intern.h" #include "webfuse/adapter/impl/jsonrpc/method.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
struct wf_impl_jsonrpc_method * wf_impl_jsonrpc_method_create( struct wf_impl_jsonrpc_method * wf_impl_jsonrpc_method_create(
char const * name, char const * method_name,
wf_impl_jsonrpc_method_invoke_fn * invoke, wf_impl_jsonrpc_method_invoke_fn * invoke,
void * user_data) void * user_data)
{ {
@ -12,7 +11,7 @@ struct wf_impl_jsonrpc_method * wf_impl_jsonrpc_method_create(
if (NULL != method) if (NULL != method)
{ {
method->next = NULL; method->next = NULL;
method->name = strdup(name); method->name = strdup(method_name);
method->invoke = invoke; method->invoke = invoke;
method->user_data = user_data; method->user_data = user_data;
} }

@ -1,31 +1,40 @@
#ifndef WF_ADAPTER_IMPL_JSONRPC_METHOD_H #ifndef WF_ADAPTER_IMPL_JSONRPC_METHOD_H
#define WF_ADAPTER_IMPL_JSONRPC_METHOD_H #define WF_ADAPTER_IMPL_JSONRPC_METHOD_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
#include <jansson.h> #include <jansson.h>
#include "webfuse/core/status.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
#endif #endif
typedef bool wf_impl_jsonrpc_method_invoke_fn( struct wf_impl_jsonrpc_request;
void * user_data,
struct json_t const * method_call);
typedef void wf_impl_jsonrpc_method_finished_fn( typedef void wf_impl_jsonrpc_method_invoke_fn(
void * user_data, struct wf_impl_jsonrpc_request * request,
wf_status status, char const * method_name,
struct json_t const * result); json_t * params,
void * user_data);
struct wf_impl_jsonrpc_method
{
struct wf_impl_jsonrpc_method * next;
char * name;
wf_impl_jsonrpc_method_invoke_fn * invoke;
void * user_data;
};
extern struct wf_impl_jsonrpc_method * wf_impl_jsonrpc_method_create(
char const * method_name,
wf_impl_jsonrpc_method_invoke_fn * invoke,
void * user_data);
extern void wf_impl_jsonrpc_method_dispose(
struct wf_impl_jsonrpc_method * method);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

@ -1,31 +0,0 @@
#ifndef WF_ADAPTER_IMPL_JSONRPC_METHOD_INTERN_H
#define WF_ADAPTER_IMPL_JSONRPC_METHOD_INTERN_H
#include "webfuse/adapter/impl/jsonrpc/method.h"
#ifdef __cplusplus
extern "C"
{
#endif
struct wf_impl_jsonrpc_method
{
struct wf_impl_jsonrpc_method * next;
char * name;
wf_impl_jsonrpc_method_invoke_fn * invoke;
void * user_data;
};
extern struct wf_impl_jsonrpc_method * wf_impl_jsonrpc_method_create(
char const * name,
wf_impl_jsonrpc_method_invoke_fn * invoke,
void * user_data);
extern void wf_impl_jsonrpc_method_dispose(
struct wf_impl_jsonrpc_method * method);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,181 @@
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include <string.h>
#include "webfuse/adapter/impl/jsonrpc/response.h"
#define WF_DEFAULT_TIMEOUT (10 * 1000)
static void wf_impl_jsonrpc_proxy_timeout(
struct wf_impl_timer * timer)
{
struct wf_impl_jsonrpc_proxy * proxy = timer->user_data;
if (proxy->request.is_pending)
{
wf_impl_jsonrpc_proxy_finished_fn * finished = proxy->request.finished;
void * user_data = proxy->request.user_data;
proxy->request.is_pending = false;
proxy->request.id = 0;
proxy->request.user_data = NULL;
proxy->request.finished = NULL;
wf_impl_timer_cancel(&proxy->request.timer);
finished(user_data, WF_BAD_TIMEOUT, NULL);
}
}
static json_t * wf_impl_jsonrpc_request_create(
char const * method,
int id,
char const * param_info,
va_list args)
{
json_t * request = json_object();
json_object_set_new(request, "method", json_string(method));
json_t * params = json_array();
for (char const * param_type = param_info; '\0' != *param_type; param_type++)
{
switch(*param_type)
{
case 's':
{
char const * const value = va_arg(args, char const *);
json_array_append_new(params, json_string(value));
}
break;
case 'i':
{
int const value = va_arg(args, int);
json_array_append_new(params, json_integer(value));
}
break;
default:
fprintf(stderr, "fatal: unknown param_type '%c'\n", *param_type);
exit(EXIT_FAILURE);
break;
}
}
json_object_set_new(request, "params", params);
if (0 != id)
{
json_object_set_new(request, "id", json_integer(id));
}
return request;
}
void wf_impl_jsonrpc_proxy_init(
struct wf_impl_jsonrpc_proxy * proxy,
struct wf_impl_timeout_manager * timeout_manager,
wf_impl_jsonrpc_send_fn * send,
void * user_data)
{
proxy->send = send;
proxy->user_data = user_data;
proxy->request.is_pending = false;
wf_impl_timer_init(&proxy->request.timer, timeout_manager);
}
void wf_impl_jsonrpc_proxy_cleanup(
struct wf_impl_jsonrpc_proxy * proxy)
{
wf_impl_timer_cleanup(&proxy->request.timer);
if (proxy->request.is_pending)
{
proxy->request.finished(proxy->request.user_data, WF_BAD, NULL);
proxy->request.is_pending = false;
}
}
void wf_impl_jsonrpc_proxy_invoke(
struct wf_impl_jsonrpc_proxy * proxy,
wf_impl_jsonrpc_proxy_finished_fn * finished,
void * user_data,
char const * method_name,
char const * param_info,
...
)
{
if (!proxy->request.is_pending)
{
proxy->request.is_pending = true;
proxy->request.finished = finished;
proxy->request.user_data = user_data;
proxy->request.id = 42;
wf_impl_timer_start(&proxy->request.timer, wf_impl_timepoint_in_msec(WF_DEFAULT_TIMEOUT),
&wf_impl_jsonrpc_proxy_timeout, proxy);
va_list args;
va_start(args, param_info);
json_t * request = wf_impl_jsonrpc_request_create(method_name, proxy->request.id, param_info, args);
va_end(args);
if (NULL != request)
{
if (!proxy->send(request, proxy->user_data))
{
proxy->request.is_pending = false;
proxy->request.finished = NULL;
proxy->request.user_data = NULL;
proxy->request.id = 0;
wf_impl_timer_cancel(&proxy->request.timer);
finished(user_data, WF_BAD, NULL);
}
json_decref(request);
}
}
else
{
finished(user_data, WF_BAD_BUSY, NULL);
}
}
extern void wf_impl_jsonrpc_proxy_notify(
struct wf_impl_jsonrpc_proxy * proxy,
char const * method_name,
char const * param_info,
...
)
{
va_list args;
va_start(args, param_info);
json_t * request = wf_impl_jsonrpc_request_create(method_name, 0, param_info, args);
va_end(args);
if (NULL != request)
{
proxy->send(request, proxy->user_data);
json_decref(request);
}
}
void wf_impl_jsonrpc_proxy_onresult(
struct wf_impl_jsonrpc_proxy * proxy,
json_t * message)
{
struct wf_impl_jsonrpc_response response;
wf_impl_jsonrpc_response_init(&response, message);
if ((proxy->request.is_pending) && (response.id == proxy->request.id))
{
wf_impl_jsonrpc_proxy_finished_fn * finished = proxy->request.finished;
void * user_data = proxy->request.user_data;
proxy->request.is_pending = false;
proxy->request.id = 0;
proxy->request.user_data = NULL;
proxy->request.finished = NULL;
wf_impl_timer_cancel(&proxy->request.timer);
finished(user_data, response.status, response.result);
}
wf_impl_jsonrpc_response_cleanup(&response);
}

@ -0,0 +1,80 @@
#ifndef WF_ADAPTER_IMPL_JSONRPC_PROXY_H
#define WF_ADAPTER_IMPL_JSONRPC_PROXY_H
#ifndef __cplusplus
#include <stdarg.h>
#include <stddef.h>
#include <stdbool.h>
#else
#include <cstdarg>
#include <cstddef>
using std::size_t;
#endif
#include <jansson.h>
#include "webfuse/adapter/impl/jsonrpc/send_fn.h"
#include "webfuse/adapter/impl/time/timeout_manager.h"
#include "webfuse/adapter/impl/time/timer.h"
#include "webfuse/core/status.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void wf_impl_jsonrpc_proxy_finished_fn(
void * user_data,
wf_status status,
struct json_t const * result);
struct wf_impl_jsonrpc_request
{
bool is_pending;
wf_impl_jsonrpc_proxy_finished_fn * finished;
void * user_data;
int id;
struct wf_impl_timer timer;
};
struct wf_impl_jsonrpc_proxy
{
struct wf_impl_jsonrpc_request request;
wf_impl_jsonrpc_send_fn * send;
void * user_data;
};
extern void wf_impl_jsonrpc_proxy_init(
struct wf_impl_jsonrpc_proxy * proxy,
struct wf_impl_timeout_manager * manager,
wf_impl_jsonrpc_send_fn * send,
void * user_data);
extern void wf_impl_jsonrpc_proxy_cleanup(
struct wf_impl_jsonrpc_proxy * proxy);
extern void wf_impl_jsonrpc_proxy_invoke(
struct wf_impl_jsonrpc_proxy * proxy,
wf_impl_jsonrpc_proxy_finished_fn * finished,
void * user_data,
char const * method_name,
char const * param_info,
...
);
extern void wf_impl_jsonrpc_proxy_notify(
struct wf_impl_jsonrpc_proxy * proxy,
char const * method_name,
char const * param_info,
...
);
extern void wf_impl_jsonrpc_proxy_onresult(
struct wf_impl_jsonrpc_proxy * proxy,
json_t * message);
#ifdef __cplusplus
}
#endif
#endif

@ -1,44 +1,82 @@
#include "webfuse/adapter/impl/jsonrpc/request.h" #include "webfuse/adapter/impl/jsonrpc/request.h"
#include "webfuse/core/status_intern.h"
#include <stdlib.h>
json_t * wf_impl_jsonrpc_request_create( struct wf_impl_jsonrpc_request
char const * method,
int id,
char const * param_info,
va_list args)
{ {
json_t * request = json_object(); int id;
json_object_set_new(request, "method", json_string(method)); wf_impl_jsonrpc_send_fn * send;
json_t * params = json_array(); void * user_data;
};
for (char const * param_type = param_info; '\0' != *param_type; param_type++)
{ bool wf_impl_jsonrpc_is_request(
switch(*param_type) json_t * message)
{ {
case 's': json_t * id = json_object_get(message, "id");
{ json_t * method = json_object_get(message, "method");
char const * const value = va_arg(args, char const *); json_t * params = json_object_get(message, "params");
json_array_append_new(params, json_string(value));
} return (json_is_integer(id) && json_is_string(method) &&
break; (json_is_array(params) || json_is_object(params)));
case 'i':
{
int const value = va_arg(args, int);
json_array_append_new(params, json_integer(value));
}
break;
default:
fprintf(stderr, "fatal: unknown param_type '%c'\n", *param_type);
exit(EXIT_FAILURE);
break;
}
}
json_object_set_new(request, "params", params);
if (0 != id)
{
json_object_set_new(request, "id", json_integer(id));
}
return request;
} }
struct wf_impl_jsonrpc_request * wf_impl_jsonrpc_request_create(
int id,
wf_impl_jsonrpc_send_fn * send,
void * user_data)
{
struct wf_impl_jsonrpc_request * request = malloc(sizeof(struct wf_impl_jsonrpc_request));
if (NULL != request)
{
request->id = id;
request->send = send;
request->user_data = user_data;
}
return request;
}
void wf_impl_jsonrpc_request_dispose(
struct wf_impl_jsonrpc_request * request)
{
free(request);
}
void * wf_impl_jsonrpc_request_get_userdata(
struct wf_impl_jsonrpc_request * request)
{
return request->user_data;
}
void wf_impl_jsonrpc_respond(
struct wf_impl_jsonrpc_request * request,
json_t * result)
{
json_t * response = json_object();
json_object_set_new(response, "result", result);
json_object_set_new(response, "id", json_integer(request->id));
request->send(response, request->user_data);
json_decref(response);
wf_impl_jsonrpc_request_dispose(request);
}
void wf_impl_jsonrpc_respond_error(
struct wf_impl_jsonrpc_request * request,
wf_status status)
{
json_t * err = json_object();
json_object_set_new(err, "code", json_integer(status));
json_object_set_new(err, "message", json_string(wf_status_tostring(status)));
json_t * response = json_object();
json_object_set_new(response, "error", err);
json_object_set_new(response, "id", json_integer(request->id));
request->send(response, request->user_data);
json_decref(response);
wf_impl_jsonrpc_request_dispose(request);
}

@ -12,17 +12,38 @@ using std::size_t;
#endif #endif
#include <jansson.h> #include <jansson.h>
#include "webfuse/core/status.h"
#include "webfuse/adapter/impl/jsonrpc/send_fn.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
#endif #endif
extern json_t * wf_impl_jsonrpc_request_create( struct wf_impl_jsonrpc_request;
char const * method,
int id, extern bool wf_impl_jsonrpc_is_request(
char const * param_info, json_t * message);
va_list args);
extern struct wf_impl_jsonrpc_request * wf_impl_jsonrpc_request_create(
int id,
wf_impl_jsonrpc_send_fn * send,
void * user_data);
extern void wf_impl_jsonrpc_request_dispose(
struct wf_impl_jsonrpc_request * request);
extern void * wf_impl_jsonrpc_request_get_userdata(
struct wf_impl_jsonrpc_request * request);
extern void wf_impl_jsonrpc_respond(
struct wf_impl_jsonrpc_request * request,
json_t * result);
extern void wf_impl_jsonrpc_respond_error(
struct wf_impl_jsonrpc_request * request,
wf_status status);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -1,26 +1,29 @@
#include "webfuse/adapter/impl/jsonrpc/response.h" #include "webfuse/adapter/impl/jsonrpc/response.h"
extern bool wf_impl_jsonrpc_is_response(
json_t * message)
{
json_t * id = json_object_get(message, "id");
json_t * err = json_object_get(message, "error");
json_t * result = json_object_get(message, "result");
return (json_is_integer(id) &&
(json_is_object(err) || (NULL != result)));
}
void wf_impl_jsonrpc_response_init( void wf_impl_jsonrpc_response_init(
struct wf_impl_jsonrpc_response * result, struct wf_impl_jsonrpc_response * result,
char const * buffer, json_t * response)
size_t length)
{ {
result->status = WF_BAD; result->status = WF_BAD;
result->id = -1; result->id = -1;
result->result = NULL; result->result = NULL;
json_t * response = json_loadb(buffer, length, 0, NULL);
if (NULL == response)
{
result->status = WF_BAD_FORMAT;
return;
}
json_t * id_holder = json_object_get(response, "id"); json_t * id_holder = json_object_get(response, "id");
if ((NULL == id_holder) || (!json_is_integer(id_holder))) if ((NULL == id_holder) || (!json_is_integer(id_holder)))
{ {
result->status = WF_BAD_FORMAT; result->status = WF_BAD_FORMAT;
json_decref(response);
return; return;
} }
@ -45,8 +48,6 @@ void wf_impl_jsonrpc_response_init(
} }
} }
} }
json_decref(response);
} }
void wf_impl_jsonrpc_response_cleanup( void wf_impl_jsonrpc_response_cleanup(

@ -2,6 +2,7 @@
#define WF_ADAPTER_IMPL_JSONRPC_RESPONSE_H #define WF_ADAPTER_IMPL_JSONRPC_RESPONSE_H
#ifndef __cplusplus #ifndef __cplusplus
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#else #else
#include <cstddef> #include <cstddef>
@ -22,10 +23,12 @@ struct wf_impl_jsonrpc_response
json_t * result; json_t * result;
}; };
extern bool wf_impl_jsonrpc_is_response(
json_t * message);
extern void wf_impl_jsonrpc_response_init( extern void wf_impl_jsonrpc_response_init(
struct wf_impl_jsonrpc_response * response, struct wf_impl_jsonrpc_response * response,
char const * buffer, json_t * message);
size_t buffer_length);
extern void wf_impl_jsonrpc_response_cleanup( extern void wf_impl_jsonrpc_response_cleanup(
struct wf_impl_jsonrpc_response * response); struct wf_impl_jsonrpc_response * response);

@ -0,0 +1,23 @@
#ifndef WF_ADAPTER_IMPL_JSONRPC_SEND_FN_H
#define WF_ADAPTER_IMPL_JSONRPC_SEND_FN_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
#include <jansson.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef bool wf_impl_jsonrpc_send_fn(
json_t * request,
void * user_data);
#ifdef __cplusplus
}
#endif
#endif

@ -1,186 +1,95 @@
#include "webfuse/adapter/impl/jsonrpc/server.h" #include "webfuse/adapter/impl/jsonrpc/server.h"
#include <string.h> #include "webfuse/adapter/impl/jsonrpc/method.h"
#include "webfuse/adapter/impl/jsonrpc/method_intern.h"
#include "webfuse/adapter/impl/jsonrpc/request.h" #include "webfuse/adapter/impl/jsonrpc/request.h"
#include "webfuse/adapter/impl/jsonrpc/response.h" #include "webfuse/core/util.h"
#define WF_DEFAULT_TIMEOUT (10 * 1000)
static struct wf_impl_jsonrpc_method const * wf_impl_jsonrpc_server_getmethod(
struct wf_impl_jsonrpc_server * server,
char const * name)
{
struct wf_impl_jsonrpc_method * method = server->methods;
while ((NULL != method) && (0 == strcmp(name, method->name)))
{
method = method->next;
}
return method;
}
static void wf_impl_jsonrpc_server_timeout(
struct wf_impl_timer * timer)
{
struct wf_impl_jsonrpc_server * server = timer->user_data;
if (server->request.is_pending) #include <string.h>
{
wf_impl_jsonrpc_method_finished_fn * finished = server->request.finished;
void * user_data = server->request.user_data;
server->request.is_pending = false;
server->request.id = 0;
server->request.user_data = NULL;
server->request.finished = NULL;
wf_impl_timer_cancel(&server->request.timer);
finished(user_data, WF_BAD_TIMEOUT, NULL);
}
}
void wf_impl_jsonrpc_server_init( void wf_impl_jsonrpc_server_init(
struct wf_impl_jsonrpc_server * server, struct wf_impl_jsonrpc_server * server)
struct wf_impl_timeout_manager * timeout_manager)
{ {
server->methods = NULL; server->methods = NULL;
server->request.is_pending = false;
wf_impl_timer_init(&server->request.timer, timeout_manager);
} }
void wf_impl_jsonrpc_server_cleanup( void wf_impl_jsonrpc_server_cleanup(
struct wf_impl_jsonrpc_server * server) struct wf_impl_jsonrpc_server * server)
{ {
wf_impl_timer_cleanup(&server->request.timer); struct wf_impl_jsonrpc_method * current = server->methods;
while (NULL != current)
if (server->request.is_pending)
{
server->request.finished(server->request.user_data, WF_BAD, NULL);
server->request.is_pending = false;
}
struct wf_impl_jsonrpc_method * method = server->methods;
while (NULL != method)
{ {
struct wf_impl_jsonrpc_method * next = method->next; struct wf_impl_jsonrpc_method * next = current->next;
method->next = NULL; wf_impl_jsonrpc_method_dispose(current);
wf_impl_jsonrpc_method_dispose(method); current = next;
method = next;
} }
server->methods = NULL; server->methods = NULL;
} }
void wf_impl_jsonrpc_server_add( void wf_impl_jsonrpc_server_add(
struct wf_impl_jsonrpc_server * server, struct wf_impl_jsonrpc_server * server,
char const * name, char const * method_name,
wf_impl_jsonrpc_method_invoke_fn * invoke, wf_impl_jsonrpc_method_invoke_fn * invoke,
void * user_data) void * user_data)
{ {
struct wf_impl_jsonrpc_method * method = wf_impl_jsonrpc_method_create(name, invoke, user_data); struct wf_impl_jsonrpc_method * method = wf_impl_jsonrpc_method_create(method_name, invoke, user_data);
method->next = server->methods; method->next = server->methods;
server->methods = method; server->methods = method;
} }
void wf_impl_jsonrpc_server_invoke( static void wf_impl_jsonrpc_server_invalid_method_invoke(
struct wf_impl_jsonrpc_server * server, struct wf_impl_jsonrpc_request * request,
wf_impl_jsonrpc_method_finished_fn * finished, char const * WF_UNUSED_PARAM(method_name),
void * user_data, json_t * WF_UNUSED_PARAM(params),
char const * method_name, void * WF_UNUSED_PARAM(user_data))
char const * param_info,
...
)
{ {
if (!server->request.is_pending) wf_impl_jsonrpc_respond_error(request, WF_BAD_NOTIMPLEMENTED);
{
struct wf_impl_jsonrpc_method const * method = wf_impl_jsonrpc_server_getmethod(server, method_name);
if (NULL != method)
{
server->request.is_pending = true;
server->request.finished = finished;
server->request.user_data = user_data;
server->request.id = 42;
wf_impl_timer_start(&server->request.timer, wf_impl_timepoint_in_msec(WF_DEFAULT_TIMEOUT),
&wf_impl_jsonrpc_server_timeout, server);
va_list args;
va_start(args, param_info);
json_t * request = wf_impl_jsonrpc_request_create(method_name, server->request.id, param_info, args);
va_end(args);
if (NULL != request)
{
if (!method->invoke(method->user_data, request))
{
server->request.is_pending = false;
server->request.finished = NULL;
server->request.user_data = NULL;
server->request.id = 0;
wf_impl_timer_cancel(&server->request.timer);
finished(user_data, WF_BAD, NULL);
}
json_decref(request);
}
}
else
{
finished(user_data, WF_BAD_NOTIMPLEMENTED, NULL);
}
}
else
{
finished(user_data, WF_BAD_BUSY, NULL);
}
} }
extern void wf_impl_jsonrpc_server_notify( static struct wf_impl_jsonrpc_method const wf_impl_jsonrpc_server_invalid_method =
struct wf_impl_jsonrpc_server * server,
char const * method_name,
char const * param_info,
...
)
{ {
struct wf_impl_jsonrpc_method const * method = wf_impl_jsonrpc_server_getmethod(server, method_name); .next = NULL,
if (NULL != method) .name = "<invalid>",
{ .invoke = &wf_impl_jsonrpc_server_invalid_method_invoke,
.user_data = NULL
};
va_list args; static struct wf_impl_jsonrpc_method const * wf_impl_jsonrpc_server_get_method(
va_start(args, param_info); struct wf_impl_jsonrpc_server * server,
json_t * request = wf_impl_jsonrpc_request_create(method_name, 0, param_info, args); char const * method_name)
va_end(args); {
if (NULL != request) struct wf_impl_jsonrpc_method const * current = server->methods;
{ while (NULL != current)
method->invoke(method->user_data, request); {
json_decref(request); if (0 == strcmp(method_name, current->name))
} {
return current;
} }
} current = current->next;
}
return &wf_impl_jsonrpc_server_invalid_method;
}
void wf_impl_jsonrpc_server_onresult( void wf_impl_jsonrpc_server_process(
struct wf_impl_jsonrpc_server * server, struct wf_impl_jsonrpc_server * server,
char const * message, json_t * request_data,
size_t length) wf_impl_jsonrpc_send_fn * send,
void * user_data)
{ {
struct wf_impl_jsonrpc_response response; json_t * method_holder = json_object_get(request_data, "method");
wf_impl_jsonrpc_response_init(&response, message, length); json_t * params = json_object_get(request_data, "params");
json_t * id_holder = json_object_get(request_data, "id");
if ((server->request.is_pending) && (response.id == server->request.id)) if (json_is_string(method_holder) &&
(json_is_array(params) || (json_is_object(params))) &&
json_is_integer(id_holder))
{ {
wf_impl_jsonrpc_method_finished_fn * finished = server->request.finished; char const * method_name = json_string_value(method_holder);
void * user_data = server->request.user_data; int id = json_integer_value(id_holder);
struct wf_impl_jsonrpc_request * request = wf_impl_jsonrpc_request_create(id, send, user_data);
struct wf_impl_jsonrpc_method const * method = wf_impl_jsonrpc_server_get_method(server, method_name);
server->request.is_pending = false; method->invoke(request, method_name, params, method->user_data);
server->request.id = 0;
server->request.user_data = NULL;
server->request.finished = NULL;
wf_impl_timer_cancel(&server->request.timer);
finished(user_data, response.status, response.result);
} }
wf_impl_jsonrpc_response_cleanup(&response);
} }

@ -3,75 +3,46 @@
#ifndef __cplusplus #ifndef __cplusplus
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#else #else
#include <cstdarg> #include <cstdarg>
#include <cstddef>
using std::size_t;
#endif #endif
#include <jansson.h> #include <jansson.h>
#include "webfuse/core/status.h"
#include "webfuse/adapter/impl/jsonrpc/send_fn.h"
#include "webfuse/adapter/impl/jsonrpc/method.h" #include "webfuse/adapter/impl/jsonrpc/method.h"
#include "webfuse/adapter/impl/time/timeout_manager.h"
#include "webfuse/adapter/impl/time/timer.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
#endif
struct wf_impl_jsonrpc_request
{ {
bool is_pending; #endif
wf_impl_jsonrpc_method_finished_fn * finished;
void * user_data;
int id;
struct wf_impl_timer timer;
};
struct wf_impl_jsonrpc_server struct wf_impl_jsonrpc_server
{ {
struct wf_impl_jsonrpc_method * methods; struct wf_impl_jsonrpc_method * methods;
struct wf_impl_jsonrpc_request request;
}; };
extern void wf_impl_jsonrpc_server_init( extern void wf_impl_jsonrpc_server_init(
struct wf_impl_jsonrpc_server * server, struct wf_impl_jsonrpc_server * server);
struct wf_impl_timeout_manager * manager);
extern void wf_impl_jsonrpc_server_cleanup( extern void wf_impl_jsonrpc_server_cleanup(
struct wf_impl_jsonrpc_server * server); struct wf_impl_jsonrpc_server * server);
extern void wf_impl_jsonrpc_server_add( extern void wf_impl_jsonrpc_server_add(
struct wf_impl_jsonrpc_server * server, struct wf_impl_jsonrpc_server * server,
char const * name, char const * method_name,
wf_impl_jsonrpc_method_invoke_fn * invoke, wf_impl_jsonrpc_method_invoke_fn * invoke,
void * user_data ); void * user_data);
extern void wf_impl_jsonrpc_server_invoke(
struct wf_impl_jsonrpc_server * server,
wf_impl_jsonrpc_method_finished_fn * finished,
void * user_data,
char const * method_name,
char const * param_info,
...
);
extern void wf_impl_jsonrpc_server_notify( extern void wf_impl_jsonrpc_server_process(
struct wf_impl_jsonrpc_server * server,
char const * method_name,
char const * param_info,
...
);
extern void wf_impl_jsonrpc_server_onresult(
struct wf_impl_jsonrpc_server * server, struct wf_impl_jsonrpc_server * server,
char const * message, json_t * request,
size_t length); wf_impl_jsonrpc_send_fn * send,
void * user_data);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

@ -4,7 +4,7 @@
#include <errno.h> #include <errno.h>
#include <jansson.h> #include <jansson.h>
#include "webfuse/adapter/impl/jsonrpc/server.h" #include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/core/util.h" #include "webfuse/core/util.h"
void wf_impl_operation_close( void wf_impl_operation_close(
@ -13,9 +13,13 @@ void wf_impl_operation_close(
struct fuse_file_info * file_info) struct fuse_file_info * file_info)
{ {
struct wf_impl_operations_context * user_data = fuse_req_userdata(request); struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_server * rpc = user_data->rpc; struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
if (NULL != rpc)
{
int handle = (int) (file_info->fh & INT_MAX);
wf_impl_jsonrpc_proxy_notify(rpc, "close", "iii", inode, handle, file_info->flags);
}
int handle = (int) (file_info->fh & INT_MAX);
wf_impl_jsonrpc_server_notify(rpc, "close", "iii", inode, handle, file_info->flags);
fuse_reply_err(request, 0); fuse_reply_err(request, 0);
} }

@ -7,7 +7,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "webfuse/adapter/impl/jsonrpc/server.h" #include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/adapter/impl/jsonrpc/util.h" #include "webfuse/adapter/impl/jsonrpc/util.h"
#include "webfuse/core/util.h" #include "webfuse/core/util.h"
@ -81,13 +81,20 @@ void wf_impl_operation_getattr (
{ {
struct fuse_ctx const * context = fuse_req_ctx(request); struct fuse_ctx const * context = fuse_req_ctx(request);
struct wf_impl_operations_context * user_data = fuse_req_userdata(request); struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_server * rpc = user_data->rpc; struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
struct wf_impl_operation_getattr_context * getattr_context = malloc(sizeof(struct wf_impl_operation_getattr_context)); if (NULL != rpc)
getattr_context->request = request; {
getattr_context->uid = context->uid; struct wf_impl_operation_getattr_context * getattr_context = malloc(sizeof(struct wf_impl_operation_getattr_context));
getattr_context->gid = context->gid; getattr_context->request = request;
getattr_context->timeout = user_data->timeout; getattr_context->uid = context->uid;
getattr_context->gid = context->gid;
getattr_context->timeout = user_data->timeout;
wf_impl_jsonrpc_server_invoke(rpc, &wf_impl_operation_getattr_finished, getattr_context, "getattr", "i", inode); wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_getattr_finished, getattr_context, "getattr", "i", inode);
}
else
{
fuse_reply_err(request, ENOENT);
}
} }

@ -10,7 +10,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "webfuse/adapter/impl/jsonrpc/server.h" #include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/adapter/impl/jsonrpc/util.h" #include "webfuse/adapter/impl/jsonrpc/util.h"
#include "webfuse/core/util.h" #include "webfuse/core/util.h"
@ -90,13 +90,20 @@ void wf_impl_operation_lookup (
{ {
struct fuse_ctx const * context = fuse_req_ctx(request); struct fuse_ctx const * context = fuse_req_ctx(request);
struct wf_impl_operations_context * user_data = fuse_req_userdata(request); struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_server * rpc = user_data->rpc; struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, parent);
struct wf_impl_operation_lookup_context * lookup_context = malloc(sizeof(struct wf_impl_operation_lookup_context)); if (NULL != rpc)
lookup_context->request = request; {
lookup_context->uid = context->uid; struct wf_impl_operation_lookup_context * lookup_context = malloc(sizeof(struct wf_impl_operation_lookup_context));
lookup_context->gid = context->gid; lookup_context->request = request;
lookup_context->timeout = user_data->timeout; lookup_context->uid = context->uid;
lookup_context->gid = context->gid;
lookup_context->timeout = user_data->timeout;
wf_impl_jsonrpc_server_invoke(rpc, &wf_impl_operation_lookup_finished, lookup_context, "lookup", "is", (int) (parent & INT_MAX), name); wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_lookup_finished, lookup_context, "lookup", "is", (int) (parent & INT_MAX), name);
}
else
{
fuse_reply_err(request, ENOENT);
}
} }

@ -4,7 +4,7 @@
#include <errno.h> #include <errno.h>
#include <jansson.h> #include <jansson.h>
#include "webfuse/adapter/impl/jsonrpc/server.h" #include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/core/util.h" #include "webfuse/core/util.h"
#include "webfuse/core/status.h" #include "webfuse/core/status.h"
@ -47,7 +47,14 @@ void wf_impl_operation_open(
struct fuse_file_info * file_info) struct fuse_file_info * file_info)
{ {
struct wf_impl_operations_context * user_data = fuse_req_userdata(request); struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_server * rpc = user_data->rpc; struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
wf_impl_jsonrpc_server_invoke(rpc, &wf_impl_operation_open_finished, request, "open", "ii", inode, file_info->flags); if (NULL != rpc)
{
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_open_finished, request, "open", "ii", inode, file_info->flags);
}
else
{
fuse_reply_err(request, ENOENT);
}
} }

@ -6,7 +6,7 @@
#include <jansson.h> #include <jansson.h>
#include <libwebsockets.h> #include <libwebsockets.h>
#include "webfuse/adapter/impl/jsonrpc/server.h" #include "webfuse/adapter/impl/jsonrpc/proxy.h"
#define WF_MAX_READ_LENGTH 4096 #define WF_MAX_READ_LENGTH 4096
@ -87,9 +87,16 @@ void wf_impl_operation_read(
struct fuse_file_info * file_info) struct fuse_file_info * file_info)
{ {
struct wf_impl_operations_context * user_data = fuse_req_userdata(request); struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_server * rpc = user_data->rpc; struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
int const length = (size <= WF_MAX_READ_LENGTH) ? (int) size : WF_MAX_READ_LENGTH; if (NULL != rpc)
int handle = (file_info->fh & INT_MAX); {
wf_impl_jsonrpc_server_invoke(rpc, &wf_impl_operation_read_finished, request, "read", "iiii", inode, handle, (int) offset, length); int const length = (size <= WF_MAX_READ_LENGTH) ? (int) size : WF_MAX_READ_LENGTH;
int handle = (file_info->fh & INT_MAX);
wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_read_finished, request, "read", "iiii", inode, handle, (int) offset, length);
}
else
{
fuse_reply_err(request, ENOENT);
}
} }

@ -8,7 +8,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "webfuse/adapter/impl/jsonrpc/server.h" #include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/core/util.h" #include "webfuse/core/util.h"
@ -137,11 +137,19 @@ void wf_impl_operation_readdir (
struct fuse_file_info * WF_UNUSED_PARAM(file_info)) struct fuse_file_info * WF_UNUSED_PARAM(file_info))
{ {
struct wf_impl_operations_context * user_data = fuse_req_userdata(request); struct wf_impl_operations_context * user_data = fuse_req_userdata(request);
struct wf_impl_jsonrpc_server * rpc = user_data->rpc; struct wf_impl_jsonrpc_proxy * rpc = wf_impl_operations_context_get_proxy(user_data, inode);
if (NULL != rpc)
{
struct wf_impl_operation_readdir_context * readdir_context = malloc(sizeof(struct wf_impl_operation_readdir_context)); struct wf_impl_operation_readdir_context * readdir_context = malloc(sizeof(struct wf_impl_operation_readdir_context));
readdir_context->request = request; readdir_context->request = request;
readdir_context->size = size; readdir_context->size = size;
readdir_context->offset = offset; readdir_context->offset = offset;
wf_impl_jsonrpc_server_invoke(rpc, &wf_impl_operation_readdir_finished, readdir_context, "readdir", "i", inode); wf_impl_jsonrpc_proxy_invoke(rpc, &wf_impl_operation_readdir_finished, readdir_context, "readdir", "i", inode);
}
else
{
fuse_reply_err(request, ENOENT);
}
} }

@ -0,0 +1,20 @@
#include "webfuse/adapter/impl/operations.h"
#include "webfuse/adapter/impl/session_manager.h"
#include "webfuse/adapter/impl/session.h"
#include <stddef.h>
struct wf_impl_jsonrpc_proxy * wf_impl_operations_context_get_proxy(
struct wf_impl_operations_context * context,
fuse_ino_t inode)
{
struct wf_impl_jsonrpc_proxy * proxy = NULL;
struct wf_impl_session_manager * session_manger = context->session_manager;
struct wf_impl_session * session = wf_impl_session_manager_get_by_inode(session_manger, inode);
if (NULL != session)
{
proxy = &session->rpc;
}
return proxy;
}

@ -7,11 +7,12 @@
extern "C" { extern "C" {
#endif #endif
struct wf_impl_jsonrpc_server; struct wf_impl_session_manager;
struct wf_impl_jsonrpc_proxy;
struct wf_impl_operations_context struct wf_impl_operations_context
{ {
struct wf_impl_jsonrpc_server * rpc; struct wf_impl_session_manager * session_manager;
double timeout; double timeout;
}; };
@ -47,6 +48,10 @@ extern void wf_impl_operation_read(
fuse_ino_t ino, size_t size, off_t off, fuse_ino_t ino, size_t size, off_t off,
struct fuse_file_info *fi); struct fuse_file_info *fi);
extern struct wf_impl_jsonrpc_proxy * wf_impl_operations_context_get_proxy(
struct wf_impl_operations_context * context,
fuse_ino_t inode);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -7,6 +7,8 @@
#include "webfuse/core/util.h" #include "webfuse/core/util.h"
#include "webfuse/adapter/impl/filesystem.h" #include "webfuse/adapter/impl/filesystem.h"
#include "webfuse/adapter/impl/credentials.h"
#include "webfuse/adapter/impl/jsonrpc/request.h"
static int wf_impl_server_protocol_callback( static int wf_impl_server_protocol_callback(
struct lws * wsi, struct lws * wsi,
@ -38,7 +40,8 @@ static int wf_impl_server_protocol_callback(
&protocol->session_manager, &protocol->session_manager,
wsi, wsi,
&protocol->authenticators, &protocol->authenticators,
&protocol->rpc); &protocol->timeout_manager,
&protocol->server);
if (NULL != session) if (NULL != session)
{ {
@ -70,20 +73,6 @@ static int wf_impl_server_protocol_callback(
return 0; return 0;
} }
static bool wf_impl_server_protocol_invoke(
void * user_data,
json_t const * request)
{
struct wf_server_protocol * protocol = user_data;
struct wf_impl_session * session = &protocol->session_manager.session;
struct wf_message * message = wf_message_create(request);
bool const result = wf_impl_session_send(session, message);
return result;
}
struct wf_server_protocol * wf_impl_server_protocol_create( struct wf_server_protocol * wf_impl_server_protocol_create(
char * mount_point) char * mount_point)
{ {
@ -116,6 +105,41 @@ void wf_impl_server_protocol_init_lws(
lws_protocol->user = protocol; lws_protocol->user = protocol;
} }
static void wf_impl_server_protocol_authenticate(
struct wf_impl_jsonrpc_request * request,
char const * WF_UNUSED_PARAM(method_name),
json_t * params,
void * WF_UNUSED_PARAM(user_data))
{
bool result = false;
json_t * type_holder = json_array_get(params, 0);
json_t * creds_holder = json_array_get(params, 1);
if (json_is_string(type_holder) && json_is_object(creds_holder))
{
char const * type = json_string_value(type_holder);
struct wf_credentials creds;
wf_impl_credentials_init(&creds, type, creds_holder);
struct wf_impl_session * session = wf_impl_jsonrpc_request_get_userdata(request);
result = wf_impl_session_authenticate(session, &creds);
wf_impl_credentials_cleanup(&creds);
}
if (result)
{
json_t * result = json_object();
wf_impl_jsonrpc_respond(request, result);
}
else
{
wf_impl_jsonrpc_respond_error(request, WF_BAD_ACCESS_DENIED);
}
}
bool wf_impl_server_protocol_init( bool wf_impl_server_protocol_init(
struct wf_server_protocol * protocol, struct wf_server_protocol * protocol,
char * mount_point) char * mount_point)
@ -124,20 +148,15 @@ bool wf_impl_server_protocol_init(
wf_impl_session_manager_init(&protocol->session_manager); wf_impl_session_manager_init(&protocol->session_manager);
wf_impl_authenticators_init(&protocol->authenticators); wf_impl_authenticators_init(&protocol->authenticators);
wf_impl_jsonrpc_server_init(&protocol->rpc, &protocol->timeout_manager); wf_impl_jsonrpc_server_init(&protocol->server);
wf_impl_jsonrpc_server_add(&protocol->rpc, "lookup", &wf_impl_server_protocol_invoke, protocol); wf_impl_jsonrpc_server_add(&protocol->server, "authenticate", &wf_impl_server_protocol_authenticate, protocol);
wf_impl_jsonrpc_server_add(&protocol->rpc, "getattr", &wf_impl_server_protocol_invoke, protocol);
wf_impl_jsonrpc_server_add(&protocol->rpc, "readdir", &wf_impl_server_protocol_invoke, protocol);
wf_impl_jsonrpc_server_add(&protocol->rpc, "open", &wf_impl_server_protocol_invoke, protocol);
wf_impl_jsonrpc_server_add(&protocol->rpc, "close", &wf_impl_server_protocol_invoke, protocol);
wf_impl_jsonrpc_server_add(&protocol->rpc, "read", &wf_impl_server_protocol_invoke, protocol);
bool const success = wf_impl_filesystem_init(&protocol->filesystem, &protocol->rpc, mount_point); bool const success = wf_impl_filesystem_init(&protocol->filesystem, &protocol->session_manager, mount_point);
// cleanup on error // cleanup on error
if (!success) if (!success)
{ {
wf_impl_jsonrpc_server_cleanup(&protocol->rpc); wf_impl_jsonrpc_server_cleanup(&protocol->server);
wf_impl_authenticators_cleanup(&protocol->authenticators); wf_impl_authenticators_cleanup(&protocol->authenticators);
wf_impl_timeout_manager_cleanup(&protocol->timeout_manager); wf_impl_timeout_manager_cleanup(&protocol->timeout_manager);
wf_impl_session_manager_cleanup(&protocol->session_manager); wf_impl_session_manager_cleanup(&protocol->session_manager);
@ -150,7 +169,7 @@ void wf_impl_server_protocol_cleanup(
struct wf_server_protocol * protocol) struct wf_server_protocol * protocol)
{ {
wf_impl_filesystem_cleanup(&protocol->filesystem); wf_impl_filesystem_cleanup(&protocol->filesystem);
wf_impl_jsonrpc_server_cleanup(&protocol->rpc); wf_impl_jsonrpc_server_cleanup(&protocol->server);
wf_impl_timeout_manager_cleanup(&protocol->timeout_manager); wf_impl_timeout_manager_cleanup(&protocol->timeout_manager);
wf_impl_authenticators_cleanup(&protocol->authenticators); wf_impl_authenticators_cleanup(&protocol->authenticators);
wf_impl_session_manager_cleanup(&protocol->session_manager); wf_impl_session_manager_cleanup(&protocol->session_manager);

@ -2,10 +2,11 @@
#define WF_ADAPTER_IMPL_SERVER_PROTOCOL_H #define WF_ADAPTER_IMPL_SERVER_PROTOCOL_H
#include "webfuse/adapter/impl/filesystem.h" #include "webfuse/adapter/impl/filesystem.h"
#include "webfuse/adapter/impl/jsonrpc/server.h" #include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/adapter/impl/time/timeout_manager.h" #include "webfuse/adapter/impl/time/timeout_manager.h"
#include "webfuse/adapter/impl/authenticators.h" #include "webfuse/adapter/impl/authenticators.h"
#include "webfuse/adapter/impl/session_manager.h" #include "webfuse/adapter/impl/session_manager.h"
#include "webfuse/adapter/impl/jsonrpc/server.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
@ -18,9 +19,9 @@ struct wf_server_protocol
{ {
struct wf_impl_timeout_manager timeout_manager; struct wf_impl_timeout_manager timeout_manager;
struct wf_impl_filesystem filesystem; struct wf_impl_filesystem filesystem;
struct wf_impl_jsonrpc_server rpc;
struct wf_impl_authenticators authenticators; struct wf_impl_authenticators authenticators;
struct wf_impl_session_manager session_manager; struct wf_impl_session_manager session_manager;
struct wf_impl_jsonrpc_server server;
}; };
extern bool wf_impl_server_protocol_init( extern bool wf_impl_server_protocol_init(

@ -2,60 +2,70 @@
#include "webfuse/adapter/impl/authenticators.h" #include "webfuse/adapter/impl/authenticators.h"
#include "webfuse/core/message_queue.h" #include "webfuse/core/message_queue.h"
#include "webfuse/core/message.h" #include "webfuse/core/message.h"
#include "webfuse/adapter/impl/jsonrpc/server.h" #include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/adapter/impl/jsonrpc/request.h"
#include "webfuse/adapter/impl/jsonrpc/response.h"
#include <libwebsockets.h> #include <libwebsockets.h>
#include <stddef.h> #include <stddef.h>
static bool wf_impl_session_send(
json_t * request,
void * user_data)
{
struct wf_impl_session * session = user_data;
struct wf_message * message = wf_message_create(request);
bool result = (session->is_authenticated || wf_impl_jsonrpc_is_response(request)) && (NULL != session->wsi);
if (result)
{
wf_message_queue_push(&session->queue, message);
lws_callback_on_writable(session->wsi);
result = true;
}
else
{
wf_message_dispose(message);
}
return result;
}
void wf_impl_session_init( void wf_impl_session_init(
struct wf_impl_session * session, struct wf_impl_session * session,
struct lws * wsi, struct lws * wsi,
struct wf_impl_authenticators * authenticators, struct wf_impl_authenticators * authenticators,
struct wf_impl_jsonrpc_server * rpc) struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server)
{ {
session->wsi = wsi; session->wsi = wsi;
session->is_authenticated = false; session->is_authenticated = false;
session->authenticators = authenticators; session->authenticators = authenticators;
session->rpc = rpc; session->server = server;
wf_impl_jsonrpc_proxy_init(&session->rpc, timeout_manager, &wf_impl_session_send, session);
wf_message_queue_init(&session->queue); wf_message_queue_init(&session->queue);
} }
void wf_impl_session_cleanup( void wf_impl_session_cleanup(
struct wf_impl_session * session) struct wf_impl_session * session)
{ {
wf_impl_jsonrpc_proxy_cleanup(&session->rpc);
wf_message_queue_cleanup(&session->queue); wf_message_queue_cleanup(&session->queue);
session->is_authenticated = false; session->is_authenticated = false;
session->wsi = NULL; session->wsi = NULL;
session->authenticators = NULL; session->authenticators = NULL;
session->rpc = NULL; session->server = NULL;
} }
void wf_impl_session_authenticate( bool wf_impl_session_authenticate(
struct wf_impl_session * session, struct wf_impl_session * session,
struct wf_credentials * creds) struct wf_credentials * creds)
{ {
session->is_authenticated = wf_impl_authenticators_authenticate(session->authenticators, creds); session->is_authenticated = wf_impl_authenticators_authenticate(session->authenticators, creds);
}
bool wf_impl_session_send(
struct wf_impl_session * session,
struct wf_message * message)
{
bool result = (session->is_authenticated) && (NULL != session->wsi);
if (result) return session->is_authenticated;
{
wf_message_queue_push(&session->queue, message);
lws_callback_on_writable(session->wsi);
result = true;
}
else
{
wf_message_dispose(message);
}
return result;
} }
void wf_impl_session_onwritable( void wf_impl_session_onwritable(
@ -80,5 +90,19 @@ void wf_impl_session_receive(
char const * data, char const * data,
size_t length) size_t length)
{ {
wf_impl_jsonrpc_server_onresult(session->rpc, data, length); json_t * message = json_loadb(data, length, 0, NULL);
if (NULL != message)
{
if (wf_impl_jsonrpc_is_response(message))
{
wf_impl_jsonrpc_proxy_onresult(&session->rpc, message);
}
else if (wf_impl_jsonrpc_is_request(message))
{
wf_impl_jsonrpc_server_process(session->server, message, &wf_impl_session_send, session);
}
json_decref(message);
}
} }

@ -10,6 +10,8 @@ using std::size_t;
#endif #endif
#include "webfuse/core/message_queue.h" #include "webfuse/core/message_queue.h"
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
#include "webfuse/adapter/impl/jsonrpc/server.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
@ -20,7 +22,7 @@ struct lws;
struct wf_message; struct wf_message;
struct wf_credentials; struct wf_credentials;
struct wf_impl_authenticators; struct wf_impl_authenticators;
struct wf_impl_jsonrpc_server; struct wf_impl_timeout_manager;
struct wf_impl_session struct wf_impl_session
{ {
@ -28,23 +30,21 @@ struct wf_impl_session
bool is_authenticated; bool is_authenticated;
struct wf_message_queue queue; struct wf_message_queue queue;
struct wf_impl_authenticators * authenticators; struct wf_impl_authenticators * authenticators;
struct wf_impl_jsonrpc_server * rpc; struct wf_impl_jsonrpc_server * server;
struct wf_impl_jsonrpc_proxy rpc;
}; };
extern void wf_impl_session_init( extern void wf_impl_session_init(
struct wf_impl_session * session, struct wf_impl_session * session,
struct lws * wsi, struct lws * wsi,
struct wf_impl_authenticators * authenticators, struct wf_impl_authenticators * authenticators,
struct wf_impl_jsonrpc_server * rpc); struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server);
extern void wf_impl_session_authenticate( extern bool wf_impl_session_authenticate(
struct wf_impl_session * session, struct wf_impl_session * session,
struct wf_credentials * creds); struct wf_credentials * creds);
extern bool wf_impl_session_send(
struct wf_impl_session * session,
struct wf_message * message);
extern void wf_impl_session_receive( extern void wf_impl_session_receive(
struct wf_impl_session * session, struct wf_impl_session * session,
char const * data, char const * data,

@ -1,10 +1,11 @@
#include "webfuse/adapter/impl/session_manager.h" #include "webfuse/adapter/impl/session_manager.h"
#include "webfuse/core/util.h"
#include <stddef.h> #include <stddef.h>
void wf_impl_session_manager_init( void wf_impl_session_manager_init(
struct wf_impl_session_manager * manager) struct wf_impl_session_manager * manager)
{ {
wf_impl_session_init(&manager->session, NULL, NULL, NULL); wf_impl_session_init(&manager->session, NULL, NULL, NULL, NULL);
} }
void wf_impl_session_manager_cleanup( void wf_impl_session_manager_cleanup(
@ -17,13 +18,14 @@ struct wf_impl_session * wf_impl_session_manager_add(
struct wf_impl_session_manager * manager, struct wf_impl_session_manager * manager,
struct lws * wsi, struct lws * wsi,
struct wf_impl_authenticators * authenticators, struct wf_impl_authenticators * authenticators,
struct wf_impl_jsonrpc_server * rpc) struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server)
{ {
struct wf_impl_session * session = NULL; struct wf_impl_session * session = NULL;
if (NULL == manager->session.wsi) if (NULL == manager->session.wsi)
{ {
session = &manager->session; session = &manager->session;
wf_impl_session_init(&manager->session, wsi, authenticators, rpc); wf_impl_session_init(&manager->session, wsi, authenticators, timeout_manager, server);
} }
return session; return session;
@ -42,6 +44,22 @@ struct wf_impl_session * wf_impl_session_manager_get(
return session; return session;
} }
struct wf_impl_session * wf_impl_session_manager_get_by_inode(
struct wf_impl_session_manager * manager,
fuse_ino_t WF_UNUSED_PARAM(inode))
{
// ToDo: use inode to determine session manager
struct wf_impl_session * session = NULL;
if (NULL != manager->session.wsi)
{
session = &manager->session;
}
return session;
}
void wf_impl_session_manager_remove( void wf_impl_session_manager_remove(
struct wf_impl_session_manager * manager, struct wf_impl_session_manager * manager,
struct lws * wsi) struct lws * wsi)

@ -6,6 +6,7 @@
#endif #endif
#include "webfuse/adapter/impl/session.h" #include "webfuse/adapter/impl/session.h"
#include "webfuse/adapter/impl/fuse_wrapper.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
@ -13,6 +14,8 @@ extern "C"
#endif #endif
struct lws; struct lws;
struct wf_impl_timeout_manager;
struct wf_impl_jsonrpc_server;
struct wf_impl_session_manager struct wf_impl_session_manager
{ {
@ -29,12 +32,17 @@ extern struct wf_impl_session * wf_impl_session_manager_add(
struct wf_impl_session_manager * manager, struct wf_impl_session_manager * manager,
struct lws * wsi, struct lws * wsi,
struct wf_impl_authenticators * authenticators, struct wf_impl_authenticators * authenticators,
struct wf_impl_jsonrpc_server * rpc); struct wf_impl_timeout_manager * timeout_manager,
struct wf_impl_jsonrpc_server * server);
extern struct wf_impl_session * wf_impl_session_manager_get( extern struct wf_impl_session * wf_impl_session_manager_get(
struct wf_impl_session_manager * manager, struct wf_impl_session_manager * manager,
struct lws * wsi); struct lws * wsi);
extern struct wf_impl_session * wf_impl_session_manager_get_by_inode(
struct wf_impl_session_manager * session_manger,
fuse_ino_t inode);
extern void wf_impl_session_manager_remove( extern void wf_impl_session_manager_remove(
struct wf_impl_session_manager * manager, struct wf_impl_session_manager * manager,
struct lws * wsi); struct lws * wsi);

@ -12,7 +12,7 @@
case WF_BAD_BUSY: return -ENOENT; case WF_BAD_BUSY: return -ENOENT;
case WF_BAD_FORMAT: return -ENOENT; case WF_BAD_FORMAT: return -ENOENT;
case WF_BAD_NOENTRY: return -ENOENT; case WF_BAD_NOENTRY: return -ENOENT;
case WF_BAD_NOACCESS: return -EACCES; case WF_BAD_ACCESS_DENIED: return -EACCES;
default: return -ENOENT; default: return -ENOENT;
} }
} }
@ -28,7 +28,7 @@ char const * wf_status_tostring(wf_status status)
case WF_BAD_BUSY: return "Bad (busy)"; case WF_BAD_BUSY: return "Bad (busy)";
case WF_BAD_FORMAT: return "Bad (format)"; case WF_BAD_FORMAT: return "Bad (format)";
case WF_BAD_NOENTRY: return "Bad (no entry)"; case WF_BAD_NOENTRY: return "Bad (no entry)";
case WF_BAD_NOACCESS: return "Bad (no access)"; case WF_BAD_ACCESS_DENIED: return "Bad (access denied)";
default: return "Bad (unknown)"; default: return "Bad (unknown)";
} }
} }

@ -8,25 +8,18 @@ static void response_parse_str(
std::string const & buffer, std::string const & buffer,
struct wf_impl_jsonrpc_response * response) struct wf_impl_jsonrpc_response * response)
{ {
wf_impl_jsonrpc_response_init(response, buffer.c_str(), buffer.size()); json_t * message = json_loadb(buffer.c_str(), buffer.size(), 0, nullptr);
if (nullptr != message)
{
wf_impl_jsonrpc_response_init(response, message);
json_decref(message);
}
} }
TEST(response_parser, test) TEST(response_parser, test)
{ {
struct wf_impl_jsonrpc_response response; struct wf_impl_jsonrpc_response response;
// invalid json
response_parse_str("", &response);
ASSERT_NE(WF_GOOD, response.status);
ASSERT_EQ(-1, response.id);
ASSERT_EQ(nullptr, response.result);
// invalid json
response_parse_str("invalid_json", &response);
ASSERT_NE(WF_GOOD, response.status);
ASSERT_EQ(-1, response.id);
ASSERT_EQ(nullptr, response.result);
// no object // no object
response_parse_str("[]", &response); response_parse_str("[]", &response);
ASSERT_NE(WF_GOOD, response.status); ASSERT_NE(WF_GOOD, response.status);

Loading…
Cancel
Save