#include "ssb.rpc.h" #include "mem.h" #include "ssb.h" #include "ssb.db.h" #include "util.js.h" #include #include #include static void _tf_ssb_rpc_gossip_ping(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) { char buffer[256]; snprintf(buffer, sizeof(buffer), "%" PRId64, (int64_t)time(NULL)); tf_ssb_connection_rpc_send( connection, flags, -request_number, (const uint8_t*)buffer, strlen(buffer), NULL, NULL, NULL); } static void _tf_ssb_rpc_blobs_get(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_connection_get_context(connection); JSValue ids = JS_GetPropertyStr(context, args, "args"); int length = tf_util_get_length(context, ids); bool success = false; for (int i = 0; i < length; i++) { JSValue arg = JS_GetPropertyUint32(context, ids, i); if (!JS_IsString(arg)) { JSValue key = JS_GetPropertyStr(context, arg, "key"); JS_FreeValue(context, arg); arg = key; } const char* id = JS_ToCString(context, arg); uint8_t* blob = NULL; size_t size = 0; const int k_send_max = 8192; if (tf_ssb_db_blob_get(ssb, id, &blob, &size)) { for (size_t offset = 0; offset < size; offset += k_send_max) { tf_ssb_connection_rpc_send( connection, k_ssb_rpc_flag_binary | k_ssb_rpc_flag_stream, -request_number, blob + offset, offset + k_send_max <= size ? k_send_max : (size - offset), NULL, NULL, NULL); } success = true; tf_free(blob); } JS_FreeCString(context, id); JS_FreeValue(context, arg); } JS_FreeValue(context, ids); tf_ssb_connection_rpc_send( connection, k_ssb_rpc_flag_json | k_ssb_rpc_flag_end_error, -request_number, (const uint8_t*)(success ? "true" : "false"), strlen(success ? "true" : "false"), NULL, NULL, NULL); } static void _tf_ssb_rpc_blobs_has(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_connection_get_context(connection); JSValue ids = JS_GetPropertyStr(context, args, "args"); JSValue id = JS_GetPropertyUint32(context, ids, 0); const char* id_str = JS_ToCString(context, id); bool has = tf_ssb_db_blob_has(ssb, id_str); JS_FreeCString(context, id_str); JS_FreeValue(context, id); JS_FreeValue(context, ids); tf_ssb_connection_rpc_send( connection, k_ssb_rpc_flag_json | k_ssb_rpc_flag_end_error, -request_number, (const uint8_t*)(has ? "true" : "false"), strlen(has ? "true" : "false"), NULL, NULL, NULL); } void tf_ssb_rpc_register(tf_ssb_t* ssb) { tf_ssb_add_rpc_callback(ssb, (const char*[]) { "gossip", "ping", NULL }, _tf_ssb_rpc_gossip_ping, NULL, NULL); tf_ssb_add_rpc_callback(ssb, (const char*[]) { "blobs", "get", NULL }, _tf_ssb_rpc_blobs_get, NULL, NULL); tf_ssb_add_rpc_callback(ssb, (const char*[]) { "blobs", "has", NULL }, _tf_ssb_rpc_blobs_has, NULL, NULL); }