Migrate query dispatch up from llcache to hlcache

As a first step in refactoring query handling to be managed
by `browser_window`, this migrates the calling of the query
handler from the llcache object code up to the hlcache.

In theory this may result in multiple queries happening for one
object, but we mitigate multiple-responses in the llcache so
all should be well.

Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
This commit is contained in:
Daniel Silverstone 2019-08-03 21:13:19 +01:00
parent 84a9c5accf
commit 09eb89e3c3
5 changed files with 117 additions and 76 deletions

View File

@ -186,6 +186,13 @@ nserror content_llcache_callback(llcache_handle *llcache,
msg_data.redirect.to = event->data.redirect.to;
content_broadcast(c, CONTENT_MSG_REDIRECT, &msg_data);
break;
case LLCACHE_EVENT_QUERY:
case LLCACHE_EVENT_QUERY_FINISHED:
/* Should never happen, because the object can't query once
* it has fetched enough that a migration to content happened.
*/
NSLOG(netsurf, DEBUG, "Encountered query related events during content handling");
break;
}
return error;

View File

@ -518,6 +518,20 @@ static nserror hlcache_llcache_callback(llcache_handle *handle,
ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw);
}
break;
case LLCACHE_EVENT_QUERY:
if (hlcache->params.llcache.cb != NULL) {
return hlcache->params.llcache.cb(
event->data.query.query,
hlcache->params.llcache.cb_ctx,
event->data.query.cb,
event->data.query.cb_pw);
} else {
return NSERROR_NOT_IMPLEMENTED;
}
break;
case LLCACHE_EVENT_QUERY_FINISHED:
/* Currently nothing to do */
break;
}
return NSERROR_OK;

View File

@ -206,12 +206,6 @@ struct llcache_object {
* Core llcache control context.
*/
struct llcache_s {
/** Handler for fetch-related queries */
llcache_query_callback query_cb;
/** Data for fetch-related query handler */
void *query_cb_pw;
/** Head of the low-level cached object list */
llcache_object *cached_objects;
@ -2267,10 +2261,18 @@ static nserror llcache_query_handle_response(bool proceed, void *cbpw)
llcache_event event;
llcache_object *object = cbpw;
if (object->fetch.outstanding_query == false) {
/* This object has already had its query answered */
return NSERROR_OK;
}
object->fetch.outstanding_query = false;
/* Tell all the users that we're leaving query state */
event.type = LLCACHE_EVENT_QUERY_FINISHED;
/* Refetch, using existing fetch parameters, if client allows us to */
if (proceed)
if (llcache_send_event_to_users(object, &event) == NSERROR_OK && proceed)
return llcache_object_refetch(object);
/* Invalidate cache-control data */
@ -2317,38 +2319,31 @@ static nserror llcache_fetch_auth(llcache_object *object, const char *realm)
auth = urldb_get_auth_details(object->url, realm);
if (auth == NULL || object->fetch.tried_with_auth == true) {
llcache_query query;
llcache_event event;
/* No authentication details, or tried what we had, so ask */
object->fetch.tried_with_auth = false;
if (llcache->query_cb != NULL) {
llcache_query query;
/* Emit query for authentication details */
query.type = LLCACHE_QUERY_AUTH;
query.url = object->url;
query.data.auth.realm = realm;
/* Emit query for authentication details */
query.type = LLCACHE_QUERY_AUTH;
query.url = object->url;
query.data.auth.realm = realm;
/* Construct the query event */
event.type = LLCACHE_EVENT_QUERY;
event.data.query.query = &query;
event.data.query.cb = llcache_query_handle_response;
event.data.query.cb_pw = object;
object->fetch.outstanding_query = true;
object->fetch.outstanding_query = true;
error = llcache->query_cb(&query, llcache->query_cb_pw,
llcache_query_handle_response, object);
if (error != NSERROR_OK) {
/* do not continue if error querying user */
error = llcache_query_handle_response(false,
object);
}
} else {
llcache_event event;
error = llcache_send_event_to_users(object, &event);
/* Mark object complete */
object->fetch.state = LLCACHE_FETCH_COMPLETE;
/* Inform client(s) that object fetch failed */
event.type = LLCACHE_EVENT_ERROR;
/** \todo More appropriate error message */
event.data.msg = messages_get("FetchFailed");
error = llcache_send_event_to_users(object, &event);
if (error != NSERROR_OK) {
/* do not continue if error querying user */
error = llcache_query_handle_response(false,
object);
}
} else {
/* Flag that we've tried to refetch with credentials, so
@ -2383,8 +2378,9 @@ static nserror llcache_fetch_cert_error(llcache_object *object,
object->fetch.tainted_tls = true;
/* Only give the user a chance if HSTS isn't in use for this fetch */
if (object->fetch.hsts_in_use == false && llcache->query_cb != NULL) {
if (object->fetch.hsts_in_use == false) {
llcache_query query;
llcache_event event;
/* Emit query for TLS */
query.type = LLCACHE_QUERY_SSL;
@ -2392,10 +2388,16 @@ static nserror llcache_fetch_cert_error(llcache_object *object,
query.data.ssl.certs = certs;
query.data.ssl.num = num;
/* Construct the query event */
event.type = LLCACHE_EVENT_QUERY;
event.data.query.query = &query;
event.data.query.cb = llcache_query_handle_response;
event.data.query.cb_pw = object;
object->fetch.outstanding_query = true;
error = llcache->query_cb(&query, llcache->query_cb_pw,
llcache_query_handle_response, object);
error = llcache_send_event_to_users(object, &event);
if (error != NSERROR_OK) {
/* do not continue if error querying user */
error = llcache_query_handle_response(false, object);
@ -3496,8 +3498,6 @@ llcache_initialise(const struct llcache_parameters *prm)
return NSERROR_NOMEM;
}
llcache->query_cb = prm->cb;
llcache->query_cb_pw = prm->cb_ctx;
llcache->limit = prm->limit;
llcache->minimum_lifetime = prm->minimum_lifetime;
llcache->minimum_bandwidth = prm->minimum_bandwidth;

View File

@ -48,45 +48,6 @@ typedef struct llcache_post_data {
} data; /**< POST data content */
} llcache_post_data;
/** Low-level cache event types */
typedef enum {
LLCACHE_EVENT_HAD_HEADERS, /**< Received all headers */
LLCACHE_EVENT_HAD_DATA, /**< Received some data */
LLCACHE_EVENT_DONE, /**< Finished fetching data */
LLCACHE_EVENT_ERROR, /**< An error occurred during fetch */
LLCACHE_EVENT_PROGRESS, /**< Fetch progress update */
LLCACHE_EVENT_REDIRECT /**< Fetch URL redirect occured */
} llcache_event_type;
/** Low-level cache events */
typedef struct {
llcache_event_type type; /**< Type of event */
union {
struct {
const uint8_t *buf; /**< Buffer of data */
size_t len; /**< Length of buffer, in bytes */
} data; /**< Received data */
const char *msg; /**< Error or progress message */
struct {
nsurl *from; /**< Redirect origin */
nsurl *to; /**< Redirect target */
} redirect; /**< Fetch URL redirect occured */
} data; /**< Event data */
} llcache_event;
/**
* Client callback for low-level cache events
*
* \param handle Handle for which event is issued
* \param event Event data
* \param pw Pointer to client-specific data
* \return NSERROR_OK on success, appropriate error otherwise.
*/
typedef nserror (*llcache_handle_callback)(llcache_handle *handle,
const llcache_event *event, void *pw);
/** Flags for low-level cache object retrieval */
enum llcache_retrieve_flag {
/* Note: We're permitted a maximum of 16 flags which must reside in the
@ -140,6 +101,58 @@ typedef struct {
*/
typedef nserror (*llcache_query_response)(bool proceed, void *cbpw);
/** Low-level cache event types */
typedef enum {
LLCACHE_EVENT_HAD_HEADERS, /**< Received all headers */
LLCACHE_EVENT_HAD_DATA, /**< Received some data */
LLCACHE_EVENT_DONE, /**< Finished fetching data */
LLCACHE_EVENT_ERROR, /**< An error occurred during fetch */
LLCACHE_EVENT_PROGRESS, /**< Fetch progress update */
LLCACHE_EVENT_QUERY, /**< Fetch has a query and is paused */
LLCACHE_EVENT_QUERY_FINISHED, /**< Fetch had a query, but it is now finished */
LLCACHE_EVENT_REDIRECT /**< Fetch URL redirect occured */
} llcache_event_type;
/**
* Low-level cache events.
*
* Lifetime of contained information is only for the duration of the event
* and must be copied if it is desirable to retain.
*/
typedef struct {
llcache_event_type type; /**< Type of event */
union {
struct {
const uint8_t *buf; /**< Buffer of data */
size_t len; /**< Length of buffer, in bytes */
} data; /**< Received data */
const char *msg; /**< Error or progress message */
struct {
nsurl *from; /**< Redirect origin */
nsurl *to; /**< Redirect target */
} redirect; /**< Fetch URL redirect occured */
struct {
llcache_query *query; /**< Query information */
llcache_query_response cb; /**< Response callback */
void *cb_pw; /**< Response callback private word */
} query; /**< Query event */
} data; /**< Event data */
} llcache_event;
/**
* Client callback for low-level cache events
*
* \param handle Handle for which event is issued
* \param event Event data
* \param pw Pointer to client-specific data
* \return NSERROR_OK on success, appropriate error otherwise.
*/
typedef nserror (*llcache_handle_callback)(llcache_handle *handle,
const llcache_event *event, void *pw);
/**
* Callback to handle fetch-related queries
*

View File

@ -234,6 +234,13 @@ static nserror download_callback(llcache_handle *handle,
case LLCACHE_EVENT_REDIRECT:
break;
case LLCACHE_EVENT_QUERY:
case LLCACHE_EVENT_QUERY_FINISHED:
/* It's *POSSIBLE* we might have to handle these here
* but how?
*/
NSLOG(netsurf, DEBUG, "Encountered query related events during download handling");
return NSERROR_NOT_IMPLEMENTED;
}
return error;