From 5e205ac8978b646d9418270310aeb38ab963c74d Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Tue, 28 Dec 2021 21:48:03 +0000 Subject: [PATCH] Fix some errors I've seen responding to blobs.get. Especially: handle sending large blobs. git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3715 ed5197a5-7fde-0310-b194-c3ffbd925b24 --- core/ssb.js | 21 +++++++++++++++++--- src/ssb.js.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/core/ssb.js b/core/ssb.js index 1d0fd1be..501cf1d7 100644 --- a/core/ssb.js +++ b/core/ssb.js @@ -168,10 +168,25 @@ ssb.addRpc(['blobs', 'has'], function(request) { }); ssb.addRpc(['blobs', 'get'], function(request) { - for (let id of request.args) { - var blob = ssb.blobGet(id); - request.send_binary(blob); + for (let arg of request.args) { + var blob; + if (arg.key) { + blob = ssb.blobGet(arg.key); + } else { + blob = ssb.blobGet(arg); + } + const k_send_max = 8192; + if (blob.byteLength > k_send_max) { + for (var i = 0; i < blob.byteLength; i += k_send_max) { + var buffer = new Uint8Array(blob, i, Math.min(blob.byteLength - i, k_send_max)); + request.send_binary(buffer); + } + } else { + request.send_binary(blob); + } + request.send_json_end(true); } + request.more(function(request) {}); }); ssb.addRpc(['gossip', 'ping'], function(request) { diff --git a/src/ssb.js.c b/src/ssb.js.c index 5ebbbc0d..11983739 100644 --- a/src/ssb.js.c +++ b/src/ssb.js.c @@ -375,6 +375,38 @@ static JSValue _tf_ssb_rpc_send_json(JSContext* context, JSValueConst this_val, return JS_UNDEFINED; } +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); + JS_FreeValue(context, connection_val); + JS_FreeCString(context, message); + JS_FreeValue(context, message_val); + return JS_UNDEFINED; +} + static JSValue _tf_ssb_rpc_more(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) { JSValue connection_val = JS_GetPropertyStr(context, this_val, "connection"); @@ -412,6 +444,29 @@ static JSValue _tf_ssb_rpc_send_binary(JSContext* context, JSValueConst this_val 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); + } + } + JS_FreeValue(context, buffer); + } JS_FreeValue(context, connection_val); return JS_UNDEFINED; } @@ -430,6 +485,7 @@ void _tf_ssb_on_rpc(tf_ssb_connection_t* connection, uint8_t flags, int32_t requ JS_SetPropertyStr(context, object, "message", message && size ? JS_NewArrayBufferCopy(context, message, size) : 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);