From 0fa9c90ab97bfdfc7024d7603396283ccce489b2 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Sat, 6 Dec 2025 14:54:30 -0500 Subject: [PATCH] core: Respond with a session message in the C websocket handler. --- src/httpd.app.c | 82 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/src/httpd.app.c b/src/httpd.app.c index f21999dc..76e08d86 100644 --- a/src/httpd.app.c +++ b/src/httpd.app.c @@ -220,7 +220,6 @@ typedef struct _app_t tf_http_request_t* request; const char* settings; JSValue credentials; - tf_taskstub_t* taskstub; JSValue process; } app_t; @@ -247,14 +246,16 @@ typedef struct _app_hello_t { app_t* app; JSValue message; + const char* user; const char* path; + char blob_id[k_id_base64_len]; + tf_ssb_identity_info_t* identity_info; } app_hello_t; static void _httpd_app_hello_work(tf_ssb_t* ssb, void* user_data) { app_hello_t* work = user_data; - char blob_id[k_id_base64_len] = { 0 }; tf_httpd_user_app_t* user_app = tf_httpd_parse_user_app_from_path(work->path, NULL); if (user_app) { @@ -262,24 +263,85 @@ static void _httpd_app_hello_work(tf_ssb_t* ssb, void* user_data) char* key = alloca(length); snprintf(key, length, "path:%s", user_app->app); const char* value = tf_ssb_db_get_property(ssb, user_app->user, key); - tf_string_set(blob_id, sizeof(blob_id), value); + tf_string_set(work->blob_id, sizeof(work->blob_id), value); tf_free((void*)value); } else if (work->path[0] == '/' && (work->path[1] == '%' || work->path[1] == '&') && strlen(work->path) >= 1 + k_blob_id_len && strstr(work->path, ".sha256")) { - memcpy(blob_id, work->path + 1, strstr(work->path, ".sha256") - work->path - 1 + strlen(".sha256")); + memcpy(work->blob_id, work->path + 1, strstr(work->path, ".sha256") - work->path - 1 + strlen(".sha256")); + } + + if (*work->blob_id) + { + work->identity_info = tf_ssb_db_get_identity_info(ssb, work->user, user_app ? user_app->user : NULL, user_app ? user_app->app : NULL); } - tf_printf("BLOB ID=%s\n", blob_id); tf_free(user_app); } +static void _http_json_send(tf_http_request_t* request, JSContext* context, JSValue value) +{ + JSValue json = JS_JSONStringify(context, value, JS_NULL, JS_NULL); + size_t json_length = 0; + const char* payload = JS_ToCStringLen(context, &json_length, json); + tf_http_request_websocket_send(request, 0x1, payload, json_length); + JS_FreeCString(context, payload); + JS_FreeValue(context, json); +} + static void _httpd_app_hello_after_work(tf_ssb_t* ssb, int status, void* user_data) { app_hello_t* work = user_data; JSContext* context = tf_ssb_get_context(ssb); + + if (!*work->blob_id) + { + JSValue object = JS_NewObject(context); + JS_SetPropertyStr(context, object, "action", JS_NewString(context, "tfrpc")); + JS_SetPropertyStr(context, object, "method", JS_NewString(context, "error")); + JSValue params = JS_NewArray(context); + size_t length = strlen(work->path) + strlen(" not found") + 1; + char* message = alloca(length); + snprintf(message, length, "%s not found", work->path); + JS_SetPropertyUint32(context, params, 0, JS_NewString(context, message)); + JS_SetPropertyStr(context, object, "params", params); + JS_SetPropertyStr(context, object, "id", JS_NewInt32(context, -1)); + _http_json_send(work->app->request, context, object); + JS_FreeValue(context, object); + } + else + { + JSValue object = JS_NewObject(context); + JS_SetPropertyStr(context, object, "action", JS_NewString(context, "session")); + JS_SetPropertyStr(context, object, "credentials", JS_DupValue(context, work->app->credentials)); + JS_SetPropertyStr(context, object, "id", JS_NewString(context, work->blob_id)); + + if (work->identity_info) + { + JSValue identities = JS_NewArray(context); + for (int i = 0; i < work->identity_info->count; i++) + { + JS_SetPropertyUint32(context, identities, i, JS_NewString(context, work->identity_info->identity[i])); + } + JS_SetPropertyStr(context, object, "identities", identities); + + JSValue names = JS_NewObject(context); + for (int i = 0; i < work->identity_info->count; i++) + { + JS_SetPropertyStr(context, names, work->identity_info->identity[i], + JS_NewString(context, work->identity_info->name[i] ? work->identity_info->name[i] : work->identity_info->identity[i])); + } + JS_SetPropertyStr(context, object, "names", names); + JS_SetPropertyStr(context, object, "identity", JS_NewString(context, work->identity_info->active_identity)); + } + _http_json_send(work->app->request, context, object); + JS_FreeValue(context, object); + } + tf_http_request_unref(work->app->request); + JS_FreeCString(context, work->user); JS_FreeCString(context, work->path); JS_FreeValue(context, work->message); + tf_free(work->identity_info); tf_free(work); } @@ -289,14 +351,18 @@ static void _httpd_app_message_hello(app_t* work, JSValue message) tf_task_t* task = tf_task_get(context); tf_ssb_t* ssb = tf_task_get_ssb(task); tf_http_request_ref(work->request); - JSValue path = JS_GetPropertyStr(context, message, "path"); + + JSValue session = JS_IsObject(work->credentials) ? JS_GetPropertyStr(context, work->credentials, "session") : JS_UNDEFINED; + const char* user = tf_util_get_property_as_string(context, session, "name"); + JS_FreeValue(context, session); + app_hello_t* hello = tf_malloc(sizeof(app_hello_t)); *hello = (app_hello_t) { .app = work, + .user = user, .message = JS_DupValue(context, message), - .path = JS_ToCString(context, path), + .path = tf_util_get_property_as_string(context, message, "path"), }; - JS_FreeValue(context, path); tf_ssb_run_work(ssb, _httpd_app_hello_work, _httpd_app_hello_after_work, hello); }