ssb.js is now entirely in C. Usual disclaimers about it not being amazingly well tested.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4111 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
213
src/ssb.js.c
213
src/ssb.js.c
@ -313,20 +313,7 @@ static JSValue _tf_ssb_sqlStream(JSContext* context, JSValueConst this_val, int
|
||||
static JSValue _tf_ssb_storeMessage(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
|
||||
char signature[crypto_sign_BYTES + 128];
|
||||
char id[crypto_hash_sha256_BYTES * 2 + 1];
|
||||
bool sequence_before_author = false;
|
||||
if (tf_ssb_verify_and_strip_signature(context, argv[0], id, sizeof(id), signature, sizeof(signature), &sequence_before_author))
|
||||
{
|
||||
if (tf_ssb_db_store_message(ssb, context, id, argv[0], signature, sequence_before_author))
|
||||
{
|
||||
tf_ssb_notify_message_added(ssb, id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("failed to verify message\n");
|
||||
}
|
||||
tf_ssb_verify_strip_and_store_message(ssb, argv[0]);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
@ -416,205 +403,12 @@ static JSValue _tf_ssb_connect(JSContext* context, JSValueConst this_val, int ar
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue _tf_ssb_rpc_send_json(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
JSValue connection_val = JS_GetPropertyStr(context, this_val, "connection");
|
||||
tf_ssb_connection_t* connection = JS_GetOpaque(connection_val, tf_ssb_get_connection_class_id());
|
||||
JSValue request_val = JS_GetPropertyStr(context, this_val, "request_number");
|
||||
int32_t request_number;
|
||||
JS_ToInt32(context, &request_number, request_val);
|
||||
JS_FreeValue(context, request_val);
|
||||
|
||||
JSValue flags_val = JS_GetPropertyStr(context, this_val, "flags");
|
||||
int32_t flags_number;
|
||||
JS_ToInt32(context, &flags_number, flags_val);
|
||||
JS_FreeValue(context, flags_val);
|
||||
|
||||
JSValue message_val = JS_JSONStringify(context, argv[0], JS_NULL, JS_NULL);
|
||||
size_t size;
|
||||
const char* message = JS_ToCStringLen(context, &size, message_val);
|
||||
|
||||
tf_ssb_connection_rpc_send(
|
||||
connection,
|
||||
k_ssb_rpc_flag_json | (flags_number & ~k_ssb_rpc_mask_type),
|
||||
-request_number,
|
||||
(const uint8_t*)message,
|
||||
size,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
JS_FreeValue(context, connection_val);
|
||||
JS_FreeCString(context, message);
|
||||
JS_FreeValue(context, message_val);
|
||||
return JS_NewInt32(context, -request_number);
|
||||
}
|
||||
|
||||
static JSValue _tf_ssb_rpc_send_json_end(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
JSValue connection_val = JS_GetPropertyStr(context, this_val, "connection");
|
||||
tf_ssb_connection_t* connection = JS_GetOpaque(connection_val, tf_ssb_get_connection_class_id());
|
||||
JSValue request_val = JS_GetPropertyStr(context, this_val, "request_number");
|
||||
int32_t request_number;
|
||||
JS_ToInt32(context, &request_number, request_val);
|
||||
JS_FreeValue(context, request_val);
|
||||
|
||||
JSValue flags_val = JS_GetPropertyStr(context, this_val, "flags");
|
||||
int32_t flags_number;
|
||||
JS_ToInt32(context, &flags_number, flags_val);
|
||||
JS_FreeValue(context, flags_val);
|
||||
|
||||
JSValue message_val = JS_JSONStringify(context, argv[0], JS_NULL, JS_NULL);
|
||||
size_t size;
|
||||
const char* message = JS_ToCStringLen(context, &size, message_val);
|
||||
|
||||
tf_ssb_connection_rpc_send(
|
||||
connection,
|
||||
k_ssb_rpc_flag_json | (flags_number & ~k_ssb_rpc_mask_type) | k_ssb_rpc_flag_end_error,
|
||||
-request_number,
|
||||
(const uint8_t*)message,
|
||||
size,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
JS_FreeValue(context, connection_val);
|
||||
JS_FreeCString(context, message);
|
||||
JS_FreeValue(context, message_val);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static void _tf_ssb_cleanup_value(tf_ssb_t* ssb, void* user_data)
|
||||
{
|
||||
JSValue callback = JS_MKPTR(JS_TAG_OBJECT, user_data);
|
||||
JS_FreeValue(tf_ssb_get_context(ssb), callback);
|
||||
}
|
||||
|
||||
static JSValue _tf_ssb_rpc_more(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
JSValue connection_val = JS_GetPropertyStr(context, this_val, "connection");
|
||||
tf_ssb_connection_t* connection = JS_GetOpaque(connection_val, tf_ssb_get_connection_class_id());
|
||||
JSValue request_val = JS_GetPropertyStr(context, this_val, "request_number");
|
||||
int32_t request_number;
|
||||
JS_ToInt32(context, &request_number, request_val);
|
||||
JS_FreeValue(context, request_val);
|
||||
|
||||
tf_ssb_connection_add_request(connection, -request_number, _tf_ssb_on_rpc, _tf_ssb_cleanup_value, JS_VALUE_GET_PTR(JS_DupValue(context, argv[0])), NULL);
|
||||
|
||||
JS_FreeValue(context, connection_val);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue _tf_ssb_rpc_send_binary(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
JSValue connection_val = JS_GetPropertyStr(context, this_val, "connection");
|
||||
tf_ssb_connection_t* connection = JS_GetOpaque(connection_val, tf_ssb_get_connection_class_id());
|
||||
JSValue request_val = JS_GetPropertyStr(context, this_val, "request_number");
|
||||
int32_t request_number;
|
||||
JS_ToInt32(context, &request_number, request_val);
|
||||
JS_FreeValue(context, request_val);
|
||||
|
||||
size_t size;
|
||||
uint8_t* message = tf_util_try_get_array_buffer(context, &size, argv[0]);
|
||||
if (message)
|
||||
{
|
||||
tf_ssb_connection_rpc_send(
|
||||
connection,
|
||||
k_ssb_rpc_flag_binary | k_ssb_rpc_flag_stream,
|
||||
-request_number,
|
||||
(const uint8_t*)message,
|
||||
size,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t offset;
|
||||
size_t element_size;
|
||||
JSValue buffer = tf_util_try_get_typed_array_buffer(context, argv[0], &offset, &size, &element_size);
|
||||
if (!JS_IsException(buffer))
|
||||
{
|
||||
size_t total_size;
|
||||
message = tf_util_try_get_array_buffer(context, &total_size, buffer);
|
||||
if (message)
|
||||
{
|
||||
tf_ssb_connection_rpc_send(
|
||||
connection,
|
||||
k_ssb_rpc_flag_binary | k_ssb_rpc_flag_stream,
|
||||
-request_number,
|
||||
(const uint8_t*)message + offset,
|
||||
size,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
JS_FreeValue(context, buffer);
|
||||
}
|
||||
JS_FreeValue(context, connection_val);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
void _tf_ssb_on_rpc(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
||||
{
|
||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
JSValue callback = JS_MKPTR(JS_TAG_OBJECT, user_data);
|
||||
JSValue object = JS_NewObject(context);
|
||||
JSValue connection_object = JS_DupValue(context, tf_ssb_connection_get_object(connection));
|
||||
JS_SetPropertyStr(context, object, "connection", connection_object);
|
||||
JS_SetPropertyStr(context, object, "flags", JS_NewUint32(context, flags));
|
||||
JS_SetPropertyStr(context, object, "request_number", JS_NewInt32(context, request_number));
|
||||
JS_SetPropertyStr(context, object, "args", JS_GetPropertyStr(context, args, "args"));
|
||||
JS_SetPropertyStr(context, object, "message", message && size ? JS_NewArrayBufferCopy(context, message, size) : JS_DupValue(context, args));
|
||||
JS_SetPropertyStr(context, object, "send_json", JS_NewCFunction(context, _tf_ssb_rpc_send_json, "send_json", 1));
|
||||
JS_SetPropertyStr(context, object, "send_binary", JS_NewCFunction(context, _tf_ssb_rpc_send_binary, "send_binary", 1));
|
||||
JS_SetPropertyStr(context, object, "send_json_end", JS_NewCFunction(context, _tf_ssb_rpc_send_json_end, "send_json_end", 1));
|
||||
JS_SetPropertyStr(context, object, "more", JS_NewCFunction(context, _tf_ssb_rpc_more, "more", 1));
|
||||
|
||||
JSValue result = JS_Call(context, callback, JS_UNDEFINED, 1, &object);
|
||||
tf_util_report_error(context, result);
|
||||
JS_FreeValue(context, result);
|
||||
JS_FreeValue(context, object);
|
||||
}
|
||||
|
||||
static JSValue _tf_ssb_add_rpc(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
|
||||
if (!JS_IsArray(context, argv[0]))
|
||||
{
|
||||
return JS_ThrowTypeError(context, "Expected argument 1 to be an array of strings.");
|
||||
}
|
||||
if (!JS_IsFunction(context, argv[1]))
|
||||
{
|
||||
return JS_ThrowTypeError(context, "Expected argument 2 to be a function.");
|
||||
}
|
||||
|
||||
enum { k_max_name_parts = 16 };
|
||||
const char* name[k_max_name_parts + 1] = { 0 };
|
||||
|
||||
int length = tf_util_get_length(context, argv[0]);
|
||||
if (length >= k_max_name_parts)
|
||||
{
|
||||
return JS_ThrowInternalError(context, "Too many parts to RPC name.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
JSValue value = JS_GetPropertyUint32(context, argv[0], i);
|
||||
name[i] = JS_ToCString(context, value);
|
||||
JS_FreeValue(context, value);
|
||||
}
|
||||
|
||||
tf_ssb_add_rpc_callback(ssb, name, _tf_ssb_on_rpc, _tf_ssb_cleanup_value, JS_VALUE_GET_PTR(JS_DupValue(context, argv[1])));
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
JS_FreeCString(context, name[i]);
|
||||
}
|
||||
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static void _tf_ssb_on_message_added_callback(tf_ssb_t* ssb, const char* id, void* user_data)
|
||||
{
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
@ -1023,13 +817,8 @@ void tf_ssb_register(JSContext* context, tf_ssb_t* ssb)
|
||||
JS_SetPropertyStr(context, object, "followingDeep", JS_NewCFunction(context, _tf_ssb_followingDeep, "followingDeep", 2));
|
||||
|
||||
/* Should be trusted only. */
|
||||
JS_SetPropertyStr(context, object, "addRpc", JS_NewCFunction(context, _tf_ssb_add_rpc, "addRpc", 2));
|
||||
JS_SetPropertyStr(context, object, "addEventListener", JS_NewCFunction(context, _tf_ssb_add_event_listener, "addEventListener", 2));
|
||||
JS_SetPropertyStr(context, object, "removeEventListener", JS_NewCFunction(context, _tf_ssb_remove_event_listener, "removeEventListener", 2));
|
||||
|
||||
JS_FreeValue(context, global);
|
||||
|
||||
tf_util_register(context);
|
||||
tf_database_register(context, tf_ssb_get_db(ssb));
|
||||
tf_ssb_run_file(context, "core/ssb.js");
|
||||
}
|
||||
|
Reference in New Issue
Block a user