From 58bb86ebe129030912d7929005beeba853d5cabd Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Mon, 10 Jun 2024 20:22:28 -0400 Subject: [PATCH] Make http.auth_query async and get its DB work off the main thread. --- core/app.js | 4 +-- core/core.js | 6 ++-- src/database.js.c | 6 ++-- src/httpd.js.c | 85 ++++++++++++++++++++++++++++++++--------------- src/ssb.js.c | 6 ++-- 5 files changed, 67 insertions(+), 40 deletions(-) diff --git a/core/app.js b/core/app.js index cacfc8e9..d0a9a625 100644 --- a/core/app.js +++ b/core/app.js @@ -83,10 +83,10 @@ App.prototype.send = function (message) { * @param {*} response * @param {*} client */ -function socket(request, response, client) { +async function socket(request, response, client) { let process; let options = {}; - let credentials = httpd.auth_query(request.headers); + let credentials = await httpd.auth_query(request.headers); response.onClose = async function () { if (process && process.task) { diff --git a/core/core.js b/core/core.js index 5efb472d..97d5eb89 100644 --- a/core/core.js +++ b/core/core.js @@ -908,7 +908,7 @@ async function useAppHandler( }, respond: do_resolve, }, - credentials: httpd.auth_query(headers), + credentials: await httpd.auth_query(headers), packageOwner: packageOwner, packageName: packageName, } @@ -1039,7 +1039,7 @@ async function blobHandler(request, response, blobId, uri) { if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) { let user = match[1]; let appName = match[2]; - let credentials = httpd.auth_query(request.headers); + let credentials = await httpd.auth_query(request.headers); if ( credentials && credentials.session && @@ -1102,7 +1102,7 @@ async function blobHandler(request, response, blobId, uri) { if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) { let user = match[1]; let appName = match[2]; - let credentials = httpd.auth_query(request.headers); + let credentials = await httpd.auth_query(request.headers); if ( credentials && credentials.session && diff --git a/src/database.js.c b/src/database.js.c index 93fc0ba7..fe6323ca 100644 --- a/src/database.js.c +++ b/src/database.js.c @@ -154,8 +154,7 @@ static JSValue _database_get(JSContext* context, JSValueConst this_val, int argc size_t length; const char* key = JS_ToCStringLen(context, &length, argv[0]); database_get_t* work = tf_malloc(sizeof(database_get_t) + strlen(database->id) + 1 + length + 1); - *work = (database_get_t) - { + *work = (database_get_t) { .id = (const char*)(work + 1), .key = (const char*)(work + 1) + strlen(database->id) + 1, .key_length = length, @@ -226,8 +225,7 @@ static JSValue _database_set(JSContext* context, JSValueConst this_val, int argc const char* value = JS_ToCStringLen(context, &value_length, argv[1]); database_set_t* work = tf_malloc(sizeof(database_set_t) + strlen(database->id) + 1 + key_length + 1 + value_length + 1); - *work = (database_set_t) - { + *work = (database_set_t) { .id = (const char*)(work + 1), .key = (const char*)(work + 1) + strlen(database->id) + 1, .value = (const char*)(work + 1) + strlen(database->id) + 1 + key_length + 1, diff --git a/src/httpd.js.c b/src/httpd.js.c index 5f46037a..f15f4c1f 100644 --- a/src/httpd.js.c +++ b/src/httpd.js.c @@ -446,6 +446,55 @@ static JSValue _httpd_set_http_redirect(JSContext* context, JSValueConst this_va return JS_UNDEFINED; } +typedef struct _auth_query_work_t +{ + const char* settings; + JSValue entry; + JSValue result; + JSValue promise[2]; +} auth_query_work_t; + +static void _httpd_auth_query_work(tf_ssb_t* ssb, void* user_data) +{ + auth_query_work_t* work = user_data; + work->settings = tf_ssb_db_get_property(ssb, "core", "settings"); +} + +static void _httpd_auth_query_after_work(tf_ssb_t* ssb, int status, void* user_data) +{ + auth_query_work_t* work = user_data; + JSContext* context = tf_ssb_get_context(ssb); + JSValue name = JS_GetPropertyStr(context, work->entry, "name"); + const char* name_string = JS_ToCString(context, name); + JSValue settings_value = work->settings ? JS_ParseJSON(context, work->settings, strlen(work->settings), NULL) : JS_UNDEFINED; + JSValue out_permissions = JS_NewObject(context); + JS_SetPropertyStr(context, work->result, "permissions", out_permissions); + JSValue permissions = !JS_IsUndefined(settings_value) ? JS_GetPropertyStr(context, settings_value, "permissions") : JS_UNDEFINED; + JSValue user_permissions = !JS_IsUndefined(permissions) ? JS_GetPropertyStr(context, permissions, name_string) : JS_UNDEFINED; + int length = !JS_IsUndefined(user_permissions) ? tf_util_get_length(context, user_permissions) : 0; + for (int i = 0; i < length; i++) + { + JSValue permission = JS_GetPropertyUint32(context, user_permissions, i); + const char* permission_string = JS_ToCString(context, permission); + JS_SetPropertyStr(context, out_permissions, permission_string, JS_TRUE); + JS_FreeCString(context, permission_string); + JS_FreeValue(context, permission); + } + JSValue error = JS_Call(context, work->promise[0], JS_UNDEFINED, 1, &work->result); + JS_FreeValue(context, work->result); + tf_util_report_error(context, error); + JS_FreeValue(context, error); + JS_FreeValue(context, work->promise[0]); + JS_FreeValue(context, work->promise[1]); + JS_FreeValue(context, user_permissions); + JS_FreeValue(context, permissions); + JS_FreeValue(context, settings_value); + tf_free((void*)work->settings); + JS_FreeCString(context, name_string); + JS_FreeValue(context, name); + tf_free(work); +} + static JSValue _httpd_auth_query(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) { tf_task_t* task = tf_task_get(context); @@ -467,33 +516,16 @@ static JSValue _httpd_auth_query(JSContext* context, JSValueConst this_val, int JSValue result = JS_UNDEFINED; if (!JS_IsUndefined(entry)) { - result = JS_NewObject(context); - JS_SetPropertyStr(context, result, "session", entry); - JSValue out_permissions = JS_NewObject(context); - JS_SetPropertyStr(context, result, "permissions", out_permissions); + JSValue value = JS_NewObject(context); + JS_SetPropertyStr(context, value, "session", entry); - JSValue name = JS_GetPropertyStr(context, entry, "name"); - const char* name_string = JS_ToCString(context, name); - - const char* settings = tf_ssb_db_get_property(ssb, "core", "settings"); - JSValue settings_value = settings ? JS_ParseJSON(context, settings, strlen(settings), NULL) : JS_UNDEFINED; - JSValue permissions = !JS_IsUndefined(settings_value) ? JS_GetPropertyStr(context, settings_value, "permissions") : JS_UNDEFINED; - JSValue user_permissions = !JS_IsUndefined(permissions) ? JS_GetPropertyStr(context, permissions, name_string) : JS_UNDEFINED; - int length = !JS_IsUndefined(user_permissions) ? tf_util_get_length(context, user_permissions) : 0; - for (int i = 0; i < length; i++) - { - JSValue permission = JS_GetPropertyUint32(context, user_permissions, i); - const char* permission_string = JS_ToCString(context, permission); - JS_SetPropertyStr(context, out_permissions, permission_string, JS_TRUE); - JS_FreeCString(context, permission_string); - JS_FreeValue(context, permission); - } - JS_FreeValue(context, user_permissions); - JS_FreeValue(context, permissions); - JS_FreeValue(context, settings_value); - tf_free((void*)settings); - JS_FreeCString(context, name_string); - JS_FreeValue(context, name); + auth_query_work_t* work = tf_malloc(sizeof(auth_query_work_t)); + *work = (auth_query_work_t) { + .entry = entry, + .result = value, + }; + result = JS_NewPromiseCapability(context, work->promise); + tf_ssb_run_work(ssb, _httpd_auth_query_work, _httpd_auth_query_after_work, work); } return result; } @@ -1315,7 +1347,6 @@ static void _httpd_endpoint_login_get_code_of_conduct_work(tf_ssb_t* ssb, void* { login_request_t* login = user_data; login->settings = tf_ssb_db_get_property(ssb, "core", "settings"); - } static void _httpd_endpoint_login_get_code_of_conduct_after_work(tf_ssb_t* ssb, int status, void* user_data) diff --git a/src/ssb.js.c b/src/ssb.js.c index 6f3c9836..f5a97e47 100644 --- a/src/ssb.js.c +++ b/src/ssb.js.c @@ -280,8 +280,7 @@ static JSValue _tf_ssb_getIdentities(JSContext* context, JSValueConst this_val, size_t user_length = 0; const char* user = JS_ToCStringLen(context, &user_length, argv[0]); identities_visit_t* work = tf_malloc(sizeof(identities_visit_t) + user_length + 1); - *work = (identities_visit_t) - { + *work = (identities_visit_t) { .context = context, }; memcpy(work->user, user, user_length + 1); @@ -331,8 +330,7 @@ static JSValue _tf_ssb_getAllIdentities(JSContext* context, JSValueConst this_va if (ssb) { identities_visit_t* work = tf_malloc(sizeof(identities_visit_t)); - *work = (identities_visit_t) - { + *work = (identities_visit_t) { .context = context, };