mirror of
https://github.com/falk-werner/webfuse-provider
synced 2024-10-27 20:44:10 +00:00
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
This commit is contained in:
parent
1d413456a2
commit
87f34fa768
@ -74,6 +74,7 @@ add_library(webfuse-adapter-static STATIC
|
||||
lib/webfuse/adapter/impl/authenticator.c
|
||||
lib/webfuse/adapter/impl/authenticators.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/timer.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/close.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/method.c
|
||||
lib/webfuse/adapter/impl/jsonrpc/request.c
|
||||
@ -185,6 +187,8 @@ install(FILES "${PROJECT_BINARY_DIR}/libwebfuse-provider.pc" DESTINATION lib${LI
|
||||
|
||||
# examples
|
||||
|
||||
pkg_check_modules(OPENSSL REQUIRED openssl)
|
||||
|
||||
if(NOT WITHOUT_EXAMPLE)
|
||||
|
||||
# libuserdb
|
||||
@ -211,9 +215,9 @@ add_executable(webfused
|
||||
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_compile_options(webfused PUBLIC ${EXTRA_CFLAGS})
|
||||
target_compile_options(webfused PUBLIC ${C_WARNINGS} ${OPENSSL_CFLAGS_OTHER} ${EXTRA_CFLAGS})
|
||||
|
||||
# provider
|
||||
|
||||
@ -229,9 +233,6 @@ target_compile_options(webfuse-provider-app PUBLIC ${EXTRA_CFLAGS})
|
||||
|
||||
# webfuse-passwd
|
||||
|
||||
pkg_check_modules(OPENSSL REQUIRED openssl)
|
||||
|
||||
|
||||
add_executable(webfuse-passwd
|
||||
example/passwd/main.c
|
||||
)
|
||||
|
104
README.md
104
README.md
@ -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.
|
||||
|
||||
## Concecpt
|
||||
## Concept
|
||||
|
||||
+---------------------+ +-------------+ +------+
|
||||
| Filesystem Provider | | webfuse | | user |
|
||||
| (e.g. Webbrowser) | | daemon | | |
|
||||
+----------+----------+ +------+------+ +---+--+
|
||||
| | |
|
||||
| +-+-+ |
|
||||
| | +--+ |
|
||||
| | | | fuse_mount |
|
||||
| | +<-+ |
|
||||
| | | |
|
||||
| | +--+ |
|
||||
| | | | start ws |
|
||||
| | +<-+ |
|
||||
| +-+-+ |
|
||||
| | |
|
||||
+-+-+ connect +-+-+ |
|
||||
| |--------------->| | |
|
||||
+-+-+ +-+-+ |
|
||||
| | |
|
||||
| +-+-+ ls +-+-+
|
||||
+-+-+ readdir | |<------------+ |
|
||||
| |<---------------+ | | |
|
||||
| | | | | |
|
||||
| | readdir_resp | | | |
|
||||
| +--------------->| | [., ..] | |
|
||||
+-+-+ | +------------>| |
|
||||
| +-+-+ +-+-+
|
||||
| | |
|
||||
![concept](doc/concept.png)
|
||||
|
||||
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:
|
||||
@ -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_FORMAT | 5 | invalid formt |
|
||||
| BAD_NOENTRY | 101 | invalid entry |
|
||||
| BAD_NOACCESS | 102 | access not allowed |
|
||||
| BAD_ACCESS_DENIED | 102 | access not allowed |
|
||||
|
||||
#### 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 |
|
||||
| params | array | method specific parameters |
|
||||
|
||||
### Requests
|
||||
### Requests (Adapter -> Provider)
|
||||
|
||||
#### lookup
|
||||
|
||||
@ -300,6 +273,73 @@ Read from an open file.
|
||||
| "identiy" | Use data as is; note that JSON strings are UTF-8 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
|
||||
|
||||
To install dependencies, see below.
|
||||
@ -318,7 +358,7 @@ By default, unit tests and example application are enabled. You can disable them
|
||||
- **WITHOUT_TESTS**: disable tests
|
||||
`cmake -DWITHOUT_TESTS=ON ..`
|
||||
|
||||
- **WITHOUT_EXAMPLE**: disable example
|
||||
- **WITHOUT_EXAMPLE**: disable example
|
||||
`cmake -DWITHOUD_EXAMPLE=ON ..`
|
||||
|
||||
## Dependencies
|
||||
|
BIN
doc/authenticate.png
Normal file
BIN
doc/authenticate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
28
doc/authenticate.uml
Normal file
28
doc/authenticate.uml
Normal file
@ -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
|
BIN
doc/concept.png
Normal file
BIN
doc/concept.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
30
doc/concept.uml
Normal file
30
doc/concept.uml
Normal file
@ -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 <getopt.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include <webfuse_adapter.h>
|
||||
#include <userdb.h>
|
||||
|
||||
|
||||
struct args
|
||||
@ -50,24 +50,16 @@ static bool authenticate(struct wf_credentials * creds, void * user_data)
|
||||
char const * password = wf_credentials_get(creds, "password");
|
||||
if ((NULL != username) && (NULL != password))
|
||||
{
|
||||
json_t * passwd = json_load_file(args->passwd_path, 0, NULL);
|
||||
if (NULL != passwd)
|
||||
struct userdb * db = userdb_create("<pepper>");
|
||||
result = userdb_load(db, args->passwd_path);
|
||||
if (result)
|
||||
{
|
||||
json_t * user = json_object_get(passwd, username);
|
||||
if (json_is_object(user))
|
||||
{
|
||||
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);
|
||||
result = userdb_check(db, username, password);
|
||||
userdb_dispose(db);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int parse_arguments(int argc, char * argv[], struct args * args)
|
||||
|
@ -6,20 +6,51 @@ export class ConnectionView {
|
||||
|
||||
this.element = document.createElement("div");
|
||||
|
||||
const connectBox = document.createElement("div");
|
||||
this.element.appendChild(connectBox);
|
||||
|
||||
const urlLabel = document.createElement("span");
|
||||
urlLabel.textContent = "URL:";
|
||||
this.element.appendChild(urlLabel);
|
||||
connectBox.appendChild(urlLabel);
|
||||
|
||||
this.urlTextbox = document.createElement("input");
|
||||
this.urlTextbox.type = "text";
|
||||
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.type = "button";
|
||||
this.connectButton.value = "connect";
|
||||
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() {
|
||||
@ -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() {
|
||||
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() {
|
||||
if (this._ws) {
|
||||
this._ws.close();
|
||||
|
@ -127,9 +127,9 @@ static char * compute_hash(
|
||||
{
|
||||
EVP_MD_CTX * context = EVP_MD_CTX_new();
|
||||
EVP_DigestInit_ex(context, digest, NULL);
|
||||
EVP_DigestUpdate(context, password, strlen(password));
|
||||
EVP_DigestUpdate(context, salt, strlen(salt));
|
||||
EVP_DigestUpdate(context, db->pepper, strlen(db->pepper));
|
||||
EVP_DigestUpdate(context, password, strlen(password)); /* Flawfinder: ignore */
|
||||
EVP_DigestUpdate(context, salt, strlen(salt)); /* Flawfinder: ignore */
|
||||
EVP_DigestUpdate(context, db->pepper, strlen(db->pepper)); /* Flawfinder: ignore */
|
||||
EVP_DigestFinal_ex(context, hash, &hash_size);
|
||||
EVP_MD_CTX_free(context);
|
||||
|
||||
|
@ -268,7 +268,7 @@ static void fs_open(
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOACCESS);
|
||||
wfp_respond_error(request, WF_BAD_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -10,7 +10,7 @@
|
||||
#define WF_BAD_FORMAT 5
|
||||
|
||||
#define WF_BAD_NOENTRY 101
|
||||
#define WF_BAD_NOACCESS 102
|
||||
#define WF_BAD_ACCESS_DENIED 102
|
||||
|
||||
typedef int wf_status;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "webfuse/adapter/impl/filesystem.h"
|
||||
#include "webfuse/adapter/impl/operations.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/server.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@ -19,7 +19,7 @@ static struct fuse_lowlevel_ops const filesystem_operations =
|
||||
|
||||
bool wf_impl_filesystem_init(
|
||||
struct wf_impl_filesystem * filesystem,
|
||||
struct wf_impl_jsonrpc_server * rpc,
|
||||
struct wf_impl_session_manager * session_manager,
|
||||
char * mount_point)
|
||||
{
|
||||
bool result = false;
|
||||
@ -29,7 +29,7 @@ bool wf_impl_filesystem_init(
|
||||
filesystem->args.argv = argv;
|
||||
filesystem->args.allocated = 0;
|
||||
|
||||
filesystem->user_data.rpc = rpc;
|
||||
filesystem->user_data.session_manager = session_manager;
|
||||
filesystem->user_data.timeout = 1.0;
|
||||
memset(&filesystem->buffer, 0, sizeof(struct fuse_buf));
|
||||
|
||||
|
@ -13,7 +13,7 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wf_impl_jsonrpc_server;
|
||||
struct wf_impl_session_manager;
|
||||
|
||||
struct wf_impl_filesystem
|
||||
{
|
||||
@ -25,7 +25,7 @@ struct wf_impl_filesystem
|
||||
|
||||
extern bool wf_impl_filesystem_init(
|
||||
struct wf_impl_filesystem * filesystem,
|
||||
struct wf_impl_jsonrpc_server * rpc,
|
||||
struct wf_impl_session_manager * session_manager,
|
||||
char * mount_point);
|
||||
|
||||
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 <string.h>
|
||||
|
||||
struct wf_impl_jsonrpc_method * wf_impl_jsonrpc_method_create(
|
||||
char const * name,
|
||||
char const * method_name,
|
||||
wf_impl_jsonrpc_method_invoke_fn * invoke,
|
||||
void * user_data)
|
||||
{
|
||||
@ -12,7 +11,7 @@ struct wf_impl_jsonrpc_method * wf_impl_jsonrpc_method_create(
|
||||
if (NULL != method)
|
||||
{
|
||||
method->next = NULL;
|
||||
method->name = strdup(name);
|
||||
method->name = strdup(method_name);
|
||||
method->invoke = invoke;
|
||||
method->user_data = user_data;
|
||||
}
|
||||
|
@ -1,31 +1,40 @@
|
||||
#ifndef WF_ADAPTER_IMPL_JSONRPC_METHOD_H
|
||||
#define WF_ADAPTER_IMPL_JSONRPC_METHOD_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#include <jansson.h>
|
||||
#include "webfuse/core/status.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef bool wf_impl_jsonrpc_method_invoke_fn(
|
||||
void * user_data,
|
||||
struct json_t const * method_call);
|
||||
struct wf_impl_jsonrpc_request;
|
||||
|
||||
typedef void wf_impl_jsonrpc_method_finished_fn(
|
||||
void * user_data,
|
||||
wf_status status,
|
||||
struct json_t const * result);
|
||||
typedef void wf_impl_jsonrpc_method_invoke_fn(
|
||||
struct wf_impl_jsonrpc_request * request,
|
||||
char const * method_name,
|
||||
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
|
||||
}
|
||||
#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
|
181
lib/webfuse/adapter/impl/jsonrpc/proxy.c
Normal file
181
lib/webfuse/adapter/impl/jsonrpc/proxy.c
Normal file
@ -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);
|
||||
}
|
||||
|
80
lib/webfuse/adapter/impl/jsonrpc/proxy.h
Normal file
80
lib/webfuse/adapter/impl/jsonrpc/proxy.h
Normal file
@ -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/core/status_intern.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
json_t * wf_impl_jsonrpc_request_create(
|
||||
char const * method,
|
||||
int id,
|
||||
char const * param_info,
|
||||
va_list args)
|
||||
struct wf_impl_jsonrpc_request
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int id;
|
||||
wf_impl_jsonrpc_send_fn * send;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
json_object_set_new(request, "params", params);
|
||||
if (0 != id)
|
||||
{
|
||||
json_object_set_new(request, "id", json_integer(id));
|
||||
}
|
||||
|
||||
return request;
|
||||
bool wf_impl_jsonrpc_is_request(
|
||||
json_t * message)
|
||||
{
|
||||
json_t * id = json_object_get(message, "id");
|
||||
json_t * method = json_object_get(message, "method");
|
||||
json_t * params = json_object_get(message, "params");
|
||||
|
||||
return (json_is_integer(id) && json_is_string(method) &&
|
||||
(json_is_array(params) || json_is_object(params)));
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
#include <jansson.h>
|
||||
#include "webfuse/core/status.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/send_fn.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern json_t * wf_impl_jsonrpc_request_create(
|
||||
char const * method,
|
||||
int id,
|
||||
char const * param_info,
|
||||
va_list args);
|
||||
struct wf_impl_jsonrpc_request;
|
||||
|
||||
extern bool wf_impl_jsonrpc_is_request(
|
||||
json_t * message);
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -1,26 +1,29 @@
|
||||
#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(
|
||||
struct wf_impl_jsonrpc_response * result,
|
||||
char const * buffer,
|
||||
size_t length)
|
||||
json_t * response)
|
||||
{
|
||||
result->status = WF_BAD;
|
||||
result->id = -1;
|
||||
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");
|
||||
if ((NULL == id_holder) || (!json_is_integer(id_holder)))
|
||||
{
|
||||
result->status = WF_BAD_FORMAT;
|
||||
json_decref(response);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -45,8 +48,6 @@ void wf_impl_jsonrpc_response_init(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
json_decref(response);
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_response_cleanup(
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define WF_ADAPTER_IMPL_JSONRPC_RESPONSE_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#else
|
||||
#include <cstddef>
|
||||
@ -22,10 +23,12 @@ struct wf_impl_jsonrpc_response
|
||||
json_t * result;
|
||||
};
|
||||
|
||||
extern bool wf_impl_jsonrpc_is_response(
|
||||
json_t * message);
|
||||
|
||||
extern void wf_impl_jsonrpc_response_init(
|
||||
struct wf_impl_jsonrpc_response * response,
|
||||
char const * buffer,
|
||||
size_t buffer_length);
|
||||
json_t * message);
|
||||
|
||||
extern void wf_impl_jsonrpc_response_cleanup(
|
||||
struct wf_impl_jsonrpc_response * response);
|
||||
|
23
lib/webfuse/adapter/impl/jsonrpc/send_fn.h
Normal file
23
lib/webfuse/adapter/impl/jsonrpc/send_fn.h
Normal file
@ -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/method.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/request.h"
|
||||
#include "webfuse/core/util.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "webfuse/adapter/impl/jsonrpc/method_intern.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/request.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/response.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)
|
||||
{
|
||||
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(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
struct wf_impl_timeout_manager * timeout_manager)
|
||||
struct wf_impl_jsonrpc_server * server)
|
||||
{
|
||||
server->methods = NULL;
|
||||
server->request.is_pending = false;
|
||||
|
||||
wf_impl_timer_init(&server->request.timer, timeout_manager);
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_server_cleanup(
|
||||
struct wf_impl_jsonrpc_server * server)
|
||||
{
|
||||
wf_impl_timer_cleanup(&server->request.timer);
|
||||
|
||||
if (server->request.is_pending)
|
||||
struct wf_impl_jsonrpc_method * current = server->methods;
|
||||
while (NULL != current)
|
||||
{
|
||||
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;
|
||||
method->next = NULL;
|
||||
wf_impl_jsonrpc_method_dispose(method);
|
||||
method = next;
|
||||
struct wf_impl_jsonrpc_method * next = current->next;
|
||||
wf_impl_jsonrpc_method_dispose(current);
|
||||
current = next;
|
||||
}
|
||||
server->methods = NULL;
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_server_add(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
char const * name,
|
||||
char const * method_name,
|
||||
wf_impl_jsonrpc_method_invoke_fn * invoke,
|
||||
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;
|
||||
server->methods = method;
|
||||
}
|
||||
|
||||
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,
|
||||
...
|
||||
)
|
||||
static void wf_impl_jsonrpc_server_invalid_method_invoke(
|
||||
struct wf_impl_jsonrpc_request * request,
|
||||
char const * WF_UNUSED_PARAM(method_name),
|
||||
json_t * WF_UNUSED_PARAM(params),
|
||||
void * WF_UNUSED_PARAM(user_data))
|
||||
{
|
||||
if (!server->request.is_pending)
|
||||
{
|
||||
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);
|
||||
}
|
||||
wf_impl_jsonrpc_respond_error(request, WF_BAD_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
extern void wf_impl_jsonrpc_server_notify(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
char const * method_name,
|
||||
char const * param_info,
|
||||
...
|
||||
)
|
||||
static struct wf_impl_jsonrpc_method const wf_impl_jsonrpc_server_invalid_method =
|
||||
{
|
||||
struct wf_impl_jsonrpc_method const * method = wf_impl_jsonrpc_server_getmethod(server, method_name);
|
||||
if (NULL != method)
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
method->invoke(method->user_data, request);
|
||||
json_decref(request);
|
||||
}
|
||||
}
|
||||
.next = NULL,
|
||||
.name = "<invalid>",
|
||||
.invoke = &wf_impl_jsonrpc_server_invalid_method_invoke,
|
||||
.user_data = NULL
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
void wf_impl_jsonrpc_server_onresult(
|
||||
static struct wf_impl_jsonrpc_method const * wf_impl_jsonrpc_server_get_method(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
char const * message,
|
||||
size_t length)
|
||||
char const * method_name)
|
||||
{
|
||||
struct wf_impl_jsonrpc_response response;
|
||||
wf_impl_jsonrpc_response_init(&response, message, length);
|
||||
|
||||
if ((server->request.is_pending) && (response.id == server->request.id))
|
||||
struct wf_impl_jsonrpc_method const * current = server->methods;
|
||||
while (NULL != current)
|
||||
{
|
||||
wf_impl_jsonrpc_method_finished_fn * finished = server->request.finished;
|
||||
void * user_data = server->request.user_data;
|
||||
if (0 == strcmp(method_name, current->name))
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
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, response.status, response.result);
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
wf_impl_jsonrpc_response_cleanup(&response);
|
||||
return &wf_impl_jsonrpc_server_invalid_method;
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_server_process(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
json_t * request_data,
|
||||
wf_impl_jsonrpc_send_fn * send,
|
||||
void * user_data)
|
||||
{
|
||||
json_t * method_holder = json_object_get(request_data, "method");
|
||||
json_t * params = json_object_get(request_data, "params");
|
||||
json_t * id_holder = json_object_get(request_data, "id");
|
||||
|
||||
if (json_is_string(method_holder) &&
|
||||
(json_is_array(params) || (json_is_object(params))) &&
|
||||
json_is_integer(id_holder))
|
||||
{
|
||||
char const * method_name = json_string_value(method_holder);
|
||||
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);
|
||||
|
||||
method->invoke(request, method_name, params, method->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,75 +3,46 @@
|
||||
|
||||
#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/core/status.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/send_fn.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
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct wf_impl_jsonrpc_request
|
||||
extern "C"
|
||||
{
|
||||
bool is_pending;
|
||||
wf_impl_jsonrpc_method_finished_fn * finished;
|
||||
void * user_data;
|
||||
int id;
|
||||
struct wf_impl_timer timer;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct wf_impl_jsonrpc_server
|
||||
{
|
||||
struct wf_impl_jsonrpc_method * methods;
|
||||
struct wf_impl_jsonrpc_request request;
|
||||
};
|
||||
|
||||
extern void wf_impl_jsonrpc_server_init(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
struct wf_impl_timeout_manager * manager);
|
||||
struct wf_impl_jsonrpc_server * server);
|
||||
|
||||
extern void wf_impl_jsonrpc_server_cleanup(
|
||||
struct wf_impl_jsonrpc_server * server);
|
||||
|
||||
extern void wf_impl_jsonrpc_server_add(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
char const * name,
|
||||
char const * method_name,
|
||||
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(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
char const * method_name,
|
||||
char const * param_info,
|
||||
...
|
||||
);
|
||||
|
||||
extern void wf_impl_jsonrpc_server_onresult(
|
||||
extern void wf_impl_jsonrpc_server_process(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
char const * message,
|
||||
size_t length);
|
||||
json_t * request,
|
||||
wf_impl_jsonrpc_send_fn * send,
|
||||
void * user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <errno.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include "webfuse/adapter/impl/jsonrpc/server.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
|
||||
#include "webfuse/core/util.h"
|
||||
|
||||
void wf_impl_operation_close(
|
||||
@ -13,9 +13,13 @@ void wf_impl_operation_close(
|
||||
struct fuse_file_info * file_info)
|
||||
{
|
||||
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 handle = (int) (file_info->fh & INT_MAX);
|
||||
wf_impl_jsonrpc_server_notify(rpc, "close", "iii", inode, handle, file_info->flags);
|
||||
if (NULL != rpc)
|
||||
{
|
||||
int handle = (int) (file_info->fh & INT_MAX);
|
||||
wf_impl_jsonrpc_proxy_notify(rpc, "close", "iii", inode, handle, file_info->flags);
|
||||
}
|
||||
|
||||
fuse_reply_err(request, 0);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <sys/stat.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/core/util.h"
|
||||
|
||||
@ -81,13 +81,20 @@ void wf_impl_operation_getattr (
|
||||
{
|
||||
struct fuse_ctx const * context = fuse_req_ctx(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));
|
||||
getattr_context->request = request;
|
||||
getattr_context->uid = context->uid;
|
||||
getattr_context->gid = context->gid;
|
||||
getattr_context->timeout = user_data->timeout;
|
||||
if (NULL != rpc)
|
||||
{
|
||||
struct wf_impl_operation_getattr_context * getattr_context = malloc(sizeof(struct wf_impl_operation_getattr_context));
|
||||
getattr_context->request = request;
|
||||
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 "webfuse/adapter/impl/jsonrpc/server.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/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 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));
|
||||
lookup_context->request = request;
|
||||
lookup_context->uid = context->uid;
|
||||
lookup_context->gid = context->gid;
|
||||
lookup_context->timeout = user_data->timeout;
|
||||
if (NULL != rpc)
|
||||
{
|
||||
struct wf_impl_operation_lookup_context * lookup_context = malloc(sizeof(struct wf_impl_operation_lookup_context));
|
||||
lookup_context->request = request;
|
||||
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 <jansson.h>
|
||||
|
||||
#include "webfuse/adapter/impl/jsonrpc/server.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
|
||||
#include "webfuse/core/util.h"
|
||||
#include "webfuse/core/status.h"
|
||||
|
||||
@ -47,7 +47,14 @@ void wf_impl_operation_open(
|
||||
struct fuse_file_info * file_info)
|
||||
{
|
||||
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 <libwebsockets.h>
|
||||
|
||||
#include "webfuse/adapter/impl/jsonrpc/server.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
|
||||
|
||||
#define WF_MAX_READ_LENGTH 4096
|
||||
|
||||
@ -87,9 +87,16 @@ void wf_impl_operation_read(
|
||||
struct fuse_file_info * file_info)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
if (NULL != rpc)
|
||||
{
|
||||
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 <unistd.h>
|
||||
|
||||
#include "webfuse/adapter/impl/jsonrpc/server.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/proxy.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 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));
|
||||
readdir_context->request = request;
|
||||
readdir_context->size = size;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
20
lib/webfuse/adapter/impl/operations.c
Normal file
20
lib/webfuse/adapter/impl/operations.c
Normal file
@ -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" {
|
||||
#endif
|
||||
|
||||
struct wf_impl_jsonrpc_server;
|
||||
struct wf_impl_session_manager;
|
||||
struct wf_impl_jsonrpc_proxy;
|
||||
|
||||
struct wf_impl_operations_context
|
||||
{
|
||||
struct wf_impl_jsonrpc_server * rpc;
|
||||
struct wf_impl_session_manager * session_manager;
|
||||
double timeout;
|
||||
};
|
||||
|
||||
@ -47,6 +48,10 @@ extern void wf_impl_operation_read(
|
||||
fuse_ino_t ino, size_t size, off_t off,
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "webfuse/core/util.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(
|
||||
struct lws * wsi,
|
||||
@ -38,7 +40,8 @@ static int wf_impl_server_protocol_callback(
|
||||
&protocol->session_manager,
|
||||
wsi,
|
||||
&protocol->authenticators,
|
||||
&protocol->rpc);
|
||||
&protocol->timeout_manager,
|
||||
&protocol->server);
|
||||
|
||||
if (NULL != session)
|
||||
{
|
||||
@ -70,20 +73,6 @@ static int wf_impl_server_protocol_callback(
|
||||
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(
|
||||
char * mount_point)
|
||||
{
|
||||
@ -116,6 +105,41 @@ void wf_impl_server_protocol_init_lws(
|
||||
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(
|
||||
struct wf_server_protocol * protocol,
|
||||
char * mount_point)
|
||||
@ -124,20 +148,15 @@ bool wf_impl_server_protocol_init(
|
||||
wf_impl_session_manager_init(&protocol->session_manager);
|
||||
wf_impl_authenticators_init(&protocol->authenticators);
|
||||
|
||||
wf_impl_jsonrpc_server_init(&protocol->rpc, &protocol->timeout_manager);
|
||||
wf_impl_jsonrpc_server_add(&protocol->rpc, "lookup", &wf_impl_server_protocol_invoke, 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);
|
||||
wf_impl_jsonrpc_server_init(&protocol->server);
|
||||
wf_impl_jsonrpc_server_add(&protocol->server, "authenticate", &wf_impl_server_protocol_authenticate, 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
|
||||
if (!success)
|
||||
{
|
||||
wf_impl_jsonrpc_server_cleanup(&protocol->rpc);
|
||||
wf_impl_jsonrpc_server_cleanup(&protocol->server);
|
||||
wf_impl_authenticators_cleanup(&protocol->authenticators);
|
||||
wf_impl_timeout_manager_cleanup(&protocol->timeout_manager);
|
||||
wf_impl_session_manager_cleanup(&protocol->session_manager);
|
||||
@ -150,7 +169,7 @@ void wf_impl_server_protocol_cleanup(
|
||||
struct wf_server_protocol * protocol)
|
||||
{
|
||||
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_authenticators_cleanup(&protocol->authenticators);
|
||||
wf_impl_session_manager_cleanup(&protocol->session_manager);
|
||||
|
@ -2,10 +2,11 @@
|
||||
#define WF_ADAPTER_IMPL_SERVER_PROTOCOL_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/authenticators.h"
|
||||
#include "webfuse/adapter/impl/session_manager.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/server.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@ -18,9 +19,9 @@ struct wf_server_protocol
|
||||
{
|
||||
struct wf_impl_timeout_manager timeout_manager;
|
||||
struct wf_impl_filesystem filesystem;
|
||||
struct wf_impl_jsonrpc_server rpc;
|
||||
struct wf_impl_authenticators authenticators;
|
||||
struct wf_impl_session_manager session_manager;
|
||||
struct wf_impl_jsonrpc_server server;
|
||||
};
|
||||
|
||||
extern bool wf_impl_server_protocol_init(
|
||||
|
@ -2,46 +2,21 @@
|
||||
#include "webfuse/adapter/impl/authenticators.h"
|
||||
#include "webfuse/core/message_queue.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 <stddef.h>
|
||||
|
||||
void wf_impl_session_init(
|
||||
struct wf_impl_session * session,
|
||||
struct lws * wsi,
|
||||
struct wf_impl_authenticators * authenticators,
|
||||
struct wf_impl_jsonrpc_server * rpc)
|
||||
{
|
||||
session->wsi = wsi;
|
||||
session->is_authenticated = false;
|
||||
session->authenticators = authenticators;
|
||||
session->rpc = rpc;
|
||||
wf_message_queue_init(&session->queue);
|
||||
}
|
||||
|
||||
void wf_impl_session_cleanup(
|
||||
struct wf_impl_session * session)
|
||||
static bool wf_impl_session_send(
|
||||
json_t * request,
|
||||
void * user_data)
|
||||
{
|
||||
wf_message_queue_cleanup(&session->queue);
|
||||
session->is_authenticated = false;
|
||||
session->wsi = NULL;
|
||||
session->authenticators = NULL;
|
||||
session->rpc = NULL;
|
||||
}
|
||||
struct wf_impl_session * session = user_data;
|
||||
struct wf_message * message = wf_message_create(request);
|
||||
|
||||
void wf_impl_session_authenticate(
|
||||
struct wf_impl_session * session,
|
||||
struct wf_credentials * 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);
|
||||
bool result = (session->is_authenticated || wf_impl_jsonrpc_is_response(request)) && (NULL != session->wsi);
|
||||
|
||||
if (result)
|
||||
{
|
||||
@ -58,6 +33,41 @@ bool wf_impl_session_send(
|
||||
return result;
|
||||
}
|
||||
|
||||
void wf_impl_session_init(
|
||||
struct wf_impl_session * session,
|
||||
struct lws * wsi,
|
||||
struct wf_impl_authenticators * authenticators,
|
||||
struct wf_impl_timeout_manager * timeout_manager,
|
||||
struct wf_impl_jsonrpc_server * server)
|
||||
{
|
||||
session->wsi = wsi;
|
||||
session->is_authenticated = false;
|
||||
session->authenticators = authenticators;
|
||||
session->server = server;
|
||||
wf_impl_jsonrpc_proxy_init(&session->rpc, timeout_manager, &wf_impl_session_send, session);
|
||||
wf_message_queue_init(&session->queue);
|
||||
}
|
||||
|
||||
void wf_impl_session_cleanup(
|
||||
struct wf_impl_session * session)
|
||||
{
|
||||
wf_impl_jsonrpc_proxy_cleanup(&session->rpc);
|
||||
wf_message_queue_cleanup(&session->queue);
|
||||
session->is_authenticated = false;
|
||||
session->wsi = NULL;
|
||||
session->authenticators = NULL;
|
||||
session->server = NULL;
|
||||
}
|
||||
|
||||
bool wf_impl_session_authenticate(
|
||||
struct wf_impl_session * session,
|
||||
struct wf_credentials * creds)
|
||||
{
|
||||
session->is_authenticated = wf_impl_authenticators_authenticate(session->authenticators, creds);
|
||||
|
||||
return session->is_authenticated;
|
||||
}
|
||||
|
||||
void wf_impl_session_onwritable(
|
||||
struct wf_impl_session * session)
|
||||
{
|
||||
@ -80,5 +90,19 @@ void wf_impl_session_receive(
|
||||
char const * data,
|
||||
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
|
||||
|
||||
#include "webfuse/core/message_queue.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/server.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@ -20,7 +22,7 @@ struct lws;
|
||||
struct wf_message;
|
||||
struct wf_credentials;
|
||||
struct wf_impl_authenticators;
|
||||
struct wf_impl_jsonrpc_server;
|
||||
struct wf_impl_timeout_manager;
|
||||
|
||||
struct wf_impl_session
|
||||
{
|
||||
@ -28,23 +30,21 @@ struct wf_impl_session
|
||||
bool is_authenticated;
|
||||
struct wf_message_queue queue;
|
||||
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(
|
||||
struct wf_impl_session * session,
|
||||
struct lws * wsi,
|
||||
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_credentials * creds);
|
||||
|
||||
extern bool wf_impl_session_send(
|
||||
struct wf_impl_session * session,
|
||||
struct wf_message * message);
|
||||
|
||||
extern void wf_impl_session_receive(
|
||||
struct wf_impl_session * session,
|
||||
char const * data,
|
||||
|
@ -1,10 +1,11 @@
|
||||
#include "webfuse/adapter/impl/session_manager.h"
|
||||
#include "webfuse/core/util.h"
|
||||
#include <stddef.h>
|
||||
|
||||
void wf_impl_session_manager_init(
|
||||
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(
|
||||
@ -17,13 +18,14 @@ struct wf_impl_session * wf_impl_session_manager_add(
|
||||
struct wf_impl_session_manager * manager,
|
||||
struct lws * wsi,
|
||||
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;
|
||||
if (NULL == manager->session.wsi)
|
||||
{
|
||||
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;
|
||||
@ -42,6 +44,22 @@ struct wf_impl_session * wf_impl_session_manager_get(
|
||||
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(
|
||||
struct wf_impl_session_manager * manager,
|
||||
struct lws * wsi)
|
||||
|
@ -6,6 +6,7 @@
|
||||
#endif
|
||||
|
||||
#include "webfuse/adapter/impl/session.h"
|
||||
#include "webfuse/adapter/impl/fuse_wrapper.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@ -13,6 +14,8 @@ extern "C"
|
||||
#endif
|
||||
|
||||
struct lws;
|
||||
struct wf_impl_timeout_manager;
|
||||
struct wf_impl_jsonrpc_server;
|
||||
|
||||
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 lws * wsi,
|
||||
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(
|
||||
struct wf_impl_session_manager * manager,
|
||||
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(
|
||||
struct wf_impl_session_manager * manager,
|
||||
struct lws * wsi);
|
||||
|
@ -12,7 +12,7 @@
|
||||
case WF_BAD_BUSY: return -ENOENT;
|
||||
case WF_BAD_FORMAT: return -ENOENT;
|
||||
case WF_BAD_NOENTRY: return -ENOENT;
|
||||
case WF_BAD_NOACCESS: return -EACCES;
|
||||
case WF_BAD_ACCESS_DENIED: return -EACCES;
|
||||
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_FORMAT: return "Bad (format)";
|
||||
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)";
|
||||
}
|
||||
}
|
||||
|
@ -8,25 +8,18 @@ static void response_parse_str(
|
||||
std::string const & buffer,
|
||||
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)
|
||||
{
|
||||
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
|
||||
response_parse_str("[]", &response);
|
||||
ASSERT_NE(WF_GOOD, response.status);
|
||||
|
Loading…
Reference in New Issue
Block a user