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:
2023-01-08 20:01:35 +00:00
parent 53e4f4341c
commit 69253432b8
9 changed files with 359 additions and 460 deletions

135
src/ssb.c
View File

@ -206,6 +206,9 @@ typedef struct _tf_ssb_connection_t
int32_t tunnel_request_number;
tf_ssb_blob_wants_t blob_wants;
bool sent_clock;
int32_t ebt_request_number;
JSValue ebt_send_clock;
JSValue object;
@ -521,6 +524,8 @@ void tf_ssb_connection_add_new_message_request(tf_ssb_connection_t* connection,
int index = tf_util_insert_index(author, connection->message_requests, connection->message_requests_count, sizeof(tf_ssb_connection_message_request_t), _message_request_compare);
if (index < connection->message_requests_count && strcmp(author, connection->message_requests[index].author) == 0)
{
connection->message_requests[index].request_number = request_number;
connection->message_requests[index].keys = keys;
return;
}
connection->message_requests = tf_resize_vec(connection->message_requests, sizeof(tf_ssb_connection_message_request_t) * (connection->message_requests_count + 1));
@ -537,6 +542,16 @@ void tf_ssb_connection_add_new_message_request(tf_ssb_connection_t* connection,
connection->message_requests_count++;
}
void tf_ssb_connection_remove_new_message_request(tf_ssb_connection_t* connection, const char* author)
{
int index = tf_util_insert_index(author, connection->message_requests, connection->message_requests_count, sizeof(tf_ssb_connection_message_request_t), _message_request_compare);
if (index < connection->message_requests_count && strcmp(author, connection->message_requests[index].author) == 0)
{
memmove(connection->message_requests + index, connection->message_requests + index + 1, sizeof(tf_ssb_connection_message_request_t) * (connection->message_requests_count - index));
connection->message_requests_count--;
}
}
static void _tf_ssb_connection_remove_request(tf_ssb_connection_t* connection, int32_t request_number)
{
tf_ssb_request_t* request = bsearch(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare);
@ -1593,6 +1608,8 @@ void _tf_ssb_connection_destroy(tf_ssb_connection_t* connection, const char* rea
!connection->tcp.data &&
!connection->connect.data)
{
JS_FreeValue(ssb->context, connection->ebt_send_clock);
connection->ebt_send_clock = JS_UNDEFINED;
tf_free(connection->message_requests);
connection->message_requests = NULL;
connection->message_requests_count = 0;
@ -2079,64 +2096,6 @@ static void _tf_ssb_connection_finalizer(JSRuntime* runtime, JSValue value)
}
}
static void _tf_ssb_connection_send_json_response(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{
if (!user_data)
{
return;
}
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_on_rpc(connection, flags, request_number, args, message, size, user_data);
}
static void _tf_ssb_connection_cleanup_value(tf_ssb_t* ssb, void* user_data)
{
if (user_data)
{
JSValue callback = JS_MKPTR(JS_TAG_OBJECT, user_data);
JS_FreeValue(tf_ssb_get_context(ssb), callback);
}
}
static JSValue _tf_ssb_connection_send_json_internal(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv, int flags)
{
tf_ssb_connection_t* connection = JS_GetOpaque(this_val, _connection_class_id);
if (!connection)
{
return JS_UNDEFINED;
}
uint32_t request_number = tf_ssb_connection_next_request_number(connection);
JSValue message_val = JS_JSONStringify(context, argv[0], JS_NULL, JS_NULL);
size_t size;
const char* message = JS_ToCStringLen(context, &size, message_val);
JS_FreeValue(context, message_val);
tf_ssb_connection_rpc_send(
connection,
flags,
request_number,
(const uint8_t*)message,
size,
_tf_ssb_connection_send_json_response,
_tf_ssb_connection_cleanup_value,
JS_IsFunction(context, argv[1]) ? JS_VALUE_GET_PTR(JS_DupValue(context, argv[1])) : NULL);
JS_FreeCString(context, message);
return JS_NewInt32(context, request_number);
}
static JSValue _tf_ssb_connection_send_json(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
return _tf_ssb_connection_send_json_internal(context, this_val, argc, argv, k_ssb_rpc_flag_json | k_ssb_rpc_flag_stream);
}
static JSValue _tf_ssb_connection_send_json_async(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
return _tf_ssb_connection_send_json_internal(context, this_val, argc, argv, k_ssb_rpc_flag_json);
}
static void _tf_ssb_connection_process_message_async(uv_async_t* async)
{
tf_ssb_connection_t* connection = async->data;
@ -2181,8 +2140,6 @@ tf_ssb_connection_t* tf_ssb_connection_create(tf_ssb_t* ssb, const char* host, c
connection->object = JS_NewObjectClass(ssb->context, _connection_class_id);
JS_SetOpaque(connection->object, connection);
JS_SetPropertyStr(context, connection->object, "send_json", JS_NewCFunction(context, _tf_ssb_connection_send_json, "send_json", 2));
JS_SetPropertyStr(context, connection->object, "send_json_async", JS_NewCFunction(context, _tf_ssb_connection_send_json_async, "send_json_async", 2));
char public_key_str[k_id_base64_len] = { 0 };
if (tf_ssb_id_bin_to_str(public_key_str, sizeof(public_key_str), public_key))
{
@ -2240,8 +2197,6 @@ tf_ssb_connection_t* tf_ssb_connection_tunnel_create(tf_ssb_t* ssb, const char*
tunnel->object = JS_NewObjectClass(ssb->context, _connection_class_id);
JS_SetOpaque(tunnel->object, tunnel);
JS_SetPropertyStr(context, tunnel->object, "send_json", JS_NewCFunction(context, _tf_ssb_connection_send_json, "send_json", 2));
JS_SetPropertyStr(context, tunnel->object, "send_json_async", JS_NewCFunction(context, _tf_ssb_connection_send_json_async, "send_json_async", 2));
JS_SetPropertyStr(context, tunnel->object, "id", JS_NewString(context, target_id));
JS_SetPropertyStr(context, tunnel->object, "is_client", JS_TRUE);
@ -2340,8 +2295,6 @@ static void _tf_ssb_on_connection(uv_stream_t* stream, int status)
uv_async_init(ssb->loop, &connection->async, _tf_ssb_connection_process_message_async);
connection->object = JS_NewObjectClass(ssb->context, _connection_class_id);
JS_SetPropertyStr(ssb->context, connection->object, "send_json", JS_NewCFunction(ssb->context, _tf_ssb_connection_send_json, "send_json", 2));
JS_SetPropertyStr(ssb->context, connection->object, "send_json_async", JS_NewCFunction(ssb->context, _tf_ssb_connection_send_json_async, "send_json_async", 2));
JS_SetOpaque(connection->object, connection);
if (uv_tcp_init(ssb->loop, &connection->tcp) != 0)
@ -3118,3 +3071,57 @@ tf_ssb_blob_wants_t* tf_ssb_connection_get_blob_wants_state(tf_ssb_connection_t*
{
return connection ? &connection->blob_wants : NULL;
}
bool tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value)
{
JSContext* context = tf_ssb_get_context(ssb);
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, value, id, sizeof(id), signature, sizeof(signature), &sequence_before_author))
{
if (tf_ssb_db_store_message(ssb, context, id, value, signature, sequence_before_author))
{
tf_ssb_notify_message_added(ssb, id);
return true;
}
}
else
{
printf("failed to verify message\n");
}
return false;
}
bool tf_ssb_connection_get_sent_clock(tf_ssb_connection_t* connection)
{
return connection->sent_clock;
}
void tf_ssb_connection_set_sent_clock(tf_ssb_connection_t* connection, bool sent_clock)
{
connection->sent_clock = sent_clock;
}
int32_t tf_ssb_connection_get_ebt_request_number(tf_ssb_connection_t* connection)
{
return connection->ebt_request_number;
}
void tf_ssb_connection_set_ebt_request_number(tf_ssb_connection_t* connection, int32_t request_number)
{
connection->ebt_request_number = request_number;
}
JSValue tf_ssb_connection_get_ebt_send_clock(tf_ssb_connection_t* connection)
{
JSContext* context = connection->ssb->context;
return JS_DupValue(context, connection->ebt_send_clock);
}
void tf_ssb_connection_set_ebt_send_clock(tf_ssb_connection_t* connection, JSValue send_clock)
{
JSContext* context = connection->ssb->context;
JS_FreeValue(context, connection->ebt_send_clock);
connection->ebt_send_clock = JS_DupValue(context, send_clock);
}