mirror of
https://github.com/falk-werner/webfuse
synced 2024-10-27 20:34:10 +00:00
190 lines
4.9 KiB
C
190 lines
4.9 KiB
C
|
#include "webfuse/impl/jsonrpc/proxy_request_manager.h"
|
||
|
#include "webfuse/status.h"
|
||
|
#include "webfuse/impl/timer/timer.h"
|
||
|
#include "webfuse/impl/jsonrpc/response_intern.h"
|
||
|
#include "webfuse/impl/jsonrpc/error.h"
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <limits.h>
|
||
|
|
||
|
struct wf_timer;
|
||
|
|
||
|
struct wf_jsonrpc_proxy_request
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request_manager * manager;
|
||
|
int id;
|
||
|
wf_jsonrpc_proxy_finished_fn * finished;
|
||
|
void * user_data;
|
||
|
struct wf_timer * timer;
|
||
|
struct wf_jsonrpc_proxy_request * next;
|
||
|
};
|
||
|
|
||
|
struct wf_jsonrpc_proxy_request_manager
|
||
|
{
|
||
|
struct wf_timer_manager * timer_manager;
|
||
|
int timeout;
|
||
|
int id;
|
||
|
struct wf_jsonrpc_proxy_request * requests;
|
||
|
};
|
||
|
|
||
|
static void
|
||
|
wf_impl_jsonrpc_proxy_request_on_timeout(
|
||
|
struct wf_timer * timer,
|
||
|
void * user_data)
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request * request = user_data;
|
||
|
|
||
|
wf_impl_jsonrpc_proxy_request_manager_cancel_request(
|
||
|
request->manager,
|
||
|
request->id,
|
||
|
WF_BAD_TIMEOUT,
|
||
|
"Timeout");
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
wf_impl_jsonrpc_proxy_request_manager_next_id(
|
||
|
struct wf_jsonrpc_proxy_request_manager * manager)
|
||
|
{
|
||
|
if (manager->id < INT_MAX)
|
||
|
{
|
||
|
manager->id++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
manager->id = 1;
|
||
|
}
|
||
|
|
||
|
return manager->id;
|
||
|
}
|
||
|
|
||
|
|
||
|
struct wf_jsonrpc_proxy_request_manager *
|
||
|
wf_impl_jsonrpc_proxy_request_manager_create(
|
||
|
struct wf_timer_manager * timer_manager,
|
||
|
int timeout)
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request_manager * manager = malloc(sizeof(struct wf_jsonrpc_proxy_request_manager));
|
||
|
manager->id = 1;
|
||
|
manager->timer_manager = timer_manager;
|
||
|
manager->timeout = timeout;
|
||
|
manager->requests = NULL;
|
||
|
|
||
|
return manager;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
wf_impl_jsonrpc_proxy_request_manager_dispose(
|
||
|
struct wf_jsonrpc_proxy_request_manager * manager)
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request * request = manager->requests;
|
||
|
while (NULL != request)
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request * next = request->next;
|
||
|
|
||
|
wf_impl_jsonrpc_propate_error(
|
||
|
request->finished, request->user_data,
|
||
|
WF_BAD, "Bad: cancelled pending request during shutdown");
|
||
|
wf_impl_timer_cancel(request->timer);
|
||
|
wf_impl_timer_dispose(request->timer);
|
||
|
free(request);
|
||
|
request = next;
|
||
|
}
|
||
|
|
||
|
free(manager);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
wf_impl_jsonrpc_proxy_request_manager_add_request(
|
||
|
struct wf_jsonrpc_proxy_request_manager * manager,
|
||
|
wf_jsonrpc_proxy_finished_fn * finished,
|
||
|
void * user_data)
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request * request = malloc(sizeof(struct wf_jsonrpc_proxy_request));
|
||
|
request->finished = finished;
|
||
|
request->user_data = user_data;
|
||
|
request->manager = manager;
|
||
|
request->id = wf_impl_jsonrpc_proxy_request_manager_next_id(manager);
|
||
|
request->timer = wf_impl_timer_create(manager->timer_manager,
|
||
|
&wf_impl_jsonrpc_proxy_request_on_timeout ,request);
|
||
|
wf_impl_timer_start(request->timer, manager->timeout);
|
||
|
|
||
|
request->next = manager->requests;
|
||
|
manager->requests = request;
|
||
|
|
||
|
return request->id;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
wf_impl_jsonrpc_proxy_request_manager_cancel_request(
|
||
|
struct wf_jsonrpc_proxy_request_manager * manager,
|
||
|
int id,
|
||
|
int error_code,
|
||
|
char const * error_message)
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request * prev = NULL;
|
||
|
struct wf_jsonrpc_proxy_request * request = manager->requests;
|
||
|
while (request != NULL)
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request * next = request->next;
|
||
|
if (id == request->id)
|
||
|
{
|
||
|
wf_impl_jsonrpc_propate_error(
|
||
|
request->finished, request->user_data,
|
||
|
error_code, error_message);
|
||
|
wf_impl_timer_cancel(request->timer);
|
||
|
wf_impl_timer_dispose(request->timer);
|
||
|
free(request);
|
||
|
|
||
|
if (NULL != prev)
|
||
|
{
|
||
|
prev->next = next;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
manager->requests = next;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
prev = request;
|
||
|
request = next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
wf_impl_jsonrpc_proxy_request_manager_finish_request(
|
||
|
struct wf_jsonrpc_proxy_request_manager * manager,
|
||
|
struct wf_jsonrpc_response * response)
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request * prev = NULL;
|
||
|
struct wf_jsonrpc_proxy_request * request = manager->requests;
|
||
|
while (request != NULL)
|
||
|
{
|
||
|
struct wf_jsonrpc_proxy_request * next = request->next;
|
||
|
if (response->id == request->id)
|
||
|
{
|
||
|
wf_jsonrpc_proxy_finished_fn * finished = request->finished;
|
||
|
void * user_data = request->user_data;
|
||
|
|
||
|
wf_impl_timer_cancel(request->timer);
|
||
|
wf_impl_timer_dispose(request->timer);
|
||
|
free(request);
|
||
|
|
||
|
if (NULL != prev)
|
||
|
{
|
||
|
prev->next = next;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
manager->requests = next;
|
||
|
}
|
||
|
|
||
|
finished(user_data, response->result, response->error);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
prev = request;
|
||
|
request = next;
|
||
|
}
|
||
|
}
|