diff --git a/src/httpd.app.c b/src/httpd.app.c index 3ef073c8..2e2a34fe 100644 --- a/src/httpd.app.c +++ b/src/httpd.app.c @@ -243,9 +243,44 @@ static void _httpd_app_kill_task(app_t* work) } } +typedef struct _app_hello_t +{ + app_t* app; + JSValue message; + const char* path; +} app_hello_t; + +static void _httpd_app_hello_work(tf_ssb_t* ssb, void* user_data) +{ + app_hello_t* work = user_data; + tf_printf("%s\n", work->path); +} + +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); + tf_http_request_unref(work->app->request); + JS_FreeCString(context, work->path); + JS_FreeValue(context, work->message); + tf_free(work); +} + static void _httpd_app_message_hello(app_t* work, JSValue message) { - /* TODO */ + JSContext* context = work->request->context; + 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"); + app_hello_t* hello = tf_malloc(sizeof(app_hello_t)); + *hello = (app_hello_t) { + .app = work, + .message = JS_DupValue(context, message), + .path = JS_ToCString(context, path), + }; + JS_FreeValue(context, path); + tf_ssb_run_work(ssb, _httpd_app_hello_work, _httpd_app_hello_after_work, hello); } static bool _httpd_app_message_call_client_api(app_t* work, JSValue message, const char* action_string) @@ -301,8 +336,6 @@ static void _httpd_app_on_message(tf_http_request_t* request, int op_code, const /* BINARY */ case 0x2: { - char* copy = tf_malloc(size + 1); - memcpy(copy, data, size); JSValue message = JS_ParseJSON(context, data, size, NULL); if (JS_IsException(message) || !JS_IsObject(message)) { diff --git a/src/ssb.c b/src/ssb.c index 21387fb4..5ee46dbd 100644 --- a/src/ssb.c +++ b/src/ssb.c @@ -1122,8 +1122,7 @@ static bool _tf_ssb_verify_and_strip_signature_internal( const char* sigstr = JS_ToCString(context, sigval); const char* sigkind = strstr(str, ".sig.ed25519"); - JSValue authorval = JS_GetPropertyStr(context, val, "author"); - const char* author = JS_ToCString(context, authorval); + const char* author = tf_util_get_property_as_string(context, val, "author"); const char* author_id = author && *author == '@' ? author + 1 : author; const char* type = strstr(author_id, ".ed25519"); @@ -1172,7 +1171,6 @@ static bool _tf_ssb_verify_and_strip_signature_internal( JS_FreeCString(context, sigstr); JS_FreeCString(context, str); JS_FreeValue(context, sigval); - JS_FreeValue(context, authorval); if (verified) { JS_FreeValue(context, signature); @@ -3046,25 +3044,21 @@ static void _tf_ssb_connection_tunnel_callback( tf_ssb_connection_rpc_send(connection, flags, -request_number, NULL, (const uint8_t*)"false", strlen("false"), NULL, NULL, NULL); JSContext* context = tf_ssb_connection_get_context(connection); - JSValue message_val = JS_GetPropertyStr(context, args, "message"); - JSValue stack_val = JS_GetPropertyStr(context, args, "stack"); + const char* message_string = tf_util_get_property_as_string(context, args, "message"); + const char* stack_string = tf_util_get_property_as_string(context, args, "stack"); char buffer[1024]; - if (!JS_IsUndefined(message_val)) + if (message_string) { - const char* message_string = JS_ToCString(context, message_val); - const char* stack_string = JS_ToCString(context, stack_val); snprintf(buffer, sizeof(buffer), "Tunnel error: %s\n%s", message_string, stack_string); - JS_FreeCString(context, message_string); - JS_FreeCString(context, stack_string); } else { snprintf(buffer, sizeof(buffer), "Tunnel error: %.*s", (int)size, message); } - JS_FreeValue(context, stack_val); - JS_FreeValue(context, message_val); + JS_FreeCString(context, message_string); + JS_FreeCString(context, stack_string); tf_ssb_connection_close(tunnel, buffer); } @@ -4049,8 +4043,7 @@ void tf_ssb_notify_message_added(tf_ssb_t* ssb, const char* author, int32_t sequ if (!JS_IsUndefined(message_keys)) { JSValue message = JS_GetPropertyStr(context, message_keys, "value"); - JSValue author = JS_GetPropertyStr(context, message, "author"); - const char* author_string = JS_ToCString(context, author); + const char* author_string = tf_util_get_property_as_string(context, message, "author"); for (tf_ssb_connection_t* connection = ssb->connections; connection; connection = connection->next) { @@ -4068,7 +4061,6 @@ void tf_ssb_notify_message_added(tf_ssb_t* ssb, const char* author, int32_t sequ } JS_FreeCString(context, author_string); - JS_FreeValue(context, author); JS_FreeValue(context, message); } } diff --git a/src/ssb.rpc.c b/src/ssb.rpc.c index 4ffe6ddd..591d9813 100644 --- a/src/ssb.rpc.c +++ b/src/ssb.rpc.c @@ -125,9 +125,7 @@ static void _tf_ssb_rpc_blobs_get(tf_ssb_connection_t* connection, uint8_t flags } else { - JSValue key = JS_GetPropertyStr(context, arg, "key"); - id = JS_ToCString(context, key); - JS_FreeValue(context, key); + id = tf_util_get_property_as_string(context, arg, "key"); } blobs_get_work_t* work = tf_malloc(sizeof(blobs_get_work_t)); @@ -313,25 +311,20 @@ static void _tf_ssb_rpc_tunnel_callback(tf_ssb_connection_t* connection, uint8_t tf_ssb_connection_remove_request(connection, request_number); JSContext* context = tf_ssb_connection_get_context(connection); - JSValue message_val = JS_GetPropertyStr(context, args, "message"); - JSValue stack_val = JS_GetPropertyStr(context, args, "stack"); + const char* message_string = tf_util_get_property_as_string(context, args, "message"); + const char* stack_string = tf_util_get_property_as_string(context, args, "stack"); char buffer[1024]; - if (!JS_IsUndefined(message_val)) + if (message_string) { - const char* message_string = JS_ToCString(context, message_val); - const char* stack_string = JS_ToCString(context, stack_val); snprintf(buffer, sizeof(buffer), "Error from tunnel: %s\n%s", message_string, stack_string); - JS_FreeCString(context, message_string); - JS_FreeCString(context, stack_string); } else { snprintf(buffer, sizeof(buffer), "Error from tunnel: %.*s", (int)size, message); } - - JS_FreeValue(context, stack_val); - JS_FreeValue(context, message_val); + JS_FreeCString(context, message_string); + JS_FreeCString(context, stack_string); } else { @@ -762,8 +755,7 @@ static void _tf_ssb_rpc_connection_room_attendants_callback( { tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); JSContext* context = tf_ssb_get_context(ssb); - JSValue type = JS_GetPropertyStr(context, args, "type"); - const char* type_string = JS_ToCString(context, type); + const char* type_string = tf_util_get_property_as_string(context, args, "type"); if (!type_string) { tf_ssb_connection_rpc_send_error(connection, flags, -request_number, "Missing type."); @@ -788,25 +780,21 @@ static void _tf_ssb_rpc_connection_room_attendants_callback( } else if (strcmp(type_string, "joined") == 0) { - JSValue id = JS_GetPropertyStr(context, args, "id"); - const char* id_string = JS_ToCString(context, id); + const char* id_string = tf_util_get_property_as_string(context, args, "id"); if (id_string) { tf_ssb_connection_add_room_attendant(connection, id_string); } JS_FreeCString(context, id_string); - JS_FreeValue(context, id); } else if (strcmp(type_string, "left") == 0) { - JSValue id = JS_GetPropertyStr(context, args, "id"); - const char* id_string = JS_ToCString(context, id); + const char* id_string = tf_util_get_property_as_string(context, args, "id"); if (id_string) { tf_ssb_connection_remove_room_attendant(connection, id_string); } JS_FreeCString(context, id_string); - JS_FreeValue(context, id); } else { @@ -815,20 +803,17 @@ static void _tf_ssb_rpc_connection_room_attendants_callback( tf_ssb_connection_rpc_send_error(connection, flags, -request_number, buffer); } JS_FreeCString(context, type_string); - JS_FreeValue(context, type); } static bool _is_error(JSContext* context, JSValue message) { - JSValue name = JS_GetPropertyStr(context, message, "name"); - const char* name_string = JS_ToCString(context, name); + const char* name_string = tf_util_get_property_as_string(context, message, "name"); bool is_error = false; if (name_string && strcmp(name_string, "Error") == 0) { is_error = true; } JS_FreeCString(context, name_string); - JS_FreeValue(context, name); return is_error; } @@ -1937,12 +1922,10 @@ static void _tf_ssb_rpc_invite_use(tf_ssb_connection_t* connection, uint8_t flag JSContext* context = tf_ssb_connection_get_context(connection); JSValue array = JS_GetPropertyStr(context, args, "args"); JSValue object = JS_GetPropertyUint32(context, array, 0); - JSValue feed = JS_GetPropertyStr(context, object, "feed"); tf_ssb_connection_get_id(connection, work->invite_public_key, sizeof(work->invite_public_key)); - const char* id = JS_ToCString(context, feed); + const char* id = tf_util_get_property_as_string(context, object, "feed"); tf_string_set(work->id, sizeof(work->id), id); JS_FreeCString(context, id); - JS_FreeValue(context, feed); JS_FreeValue(context, object); JS_FreeValue(context, array); tf_ssb_connection_run_work(connection, _tf_ssb_rpc_invite_use_work, _tf_ssb_rpc_invite_use_after_work, work); diff --git a/src/util.js.c b/src/util.js.c index 52bee993..a6cb3689 100644 --- a/src/util.js.c +++ b/src/util.js.c @@ -502,6 +502,24 @@ int tf_util_get_length(JSContext* context, JSValue value) return result; } +const char* tf_util_get_property_as_string(JSContext* context, JSValue object, const char* key) +{ + if (!JS_IsObject(object)) + { + return NULL; + } + + JSValue value = JS_GetPropertyStr(context, object, key); + if (JS_IsUndefined(value)) + { + return NULL; + } + + const char* string = JS_ToCString(context, value); + JS_FreeValue(context, value); + return string; +} + int tf_util_insert_index(const void* key, const void* base, size_t count, size_t size, int (*compare)(const void*, const void*)) { int lower = 0; diff --git a/src/util.js.h b/src/util.js.h index 09383697..3ebf52c9 100644 --- a/src/util.js.h +++ b/src/util.js.h @@ -71,6 +71,15 @@ bool tf_util_report_error(JSContext* context, JSValue value); */ int tf_util_get_length(JSContext* context, JSValue value); +/** +** Get an object property by string key as a C-style string. +** @param context The JS context. +** @param object The object. +** @param key The property key. +** @return A string to be freed with JS_FreeCString() or NULL. +*/ +const char* tf_util_get_property_as_string(JSContext* context, JSValue object, const char* key); + /** ** Get the index at which to insert into an array in order to preserve sorted order. ** @param key The key being inserted.