diff --git a/core/ssb.js b/core/ssb.js index fc9df420..e84b6fb7 100644 --- a/core/ssb.js +++ b/core/ssb.js @@ -226,28 +226,6 @@ ssb.addRpc(['room', 'attendants'], function(request) { g_attendants[request.connection.id] = request; }); -ssb.addRpc(['tunnel', 'connect'], function(request) { - if (!request.args[0].origin && - request.args[0].portal && - request.args[0].target) { - let target_connection = ssb.getConnection(request.args[0].target); - let target_request_number = target_connection.send_json({ - 'name': ['tunnel', 'connect'], - 'args': [{ - 'origin': request.connection.id, - 'portal': request.args[0].portal, - 'target': request.args[0].target, - }], - 'type': 'duplex', - }); - ssb.tunnel(request.connection, -request.request_number, target_connection, target_request_number); - } else if (request.args[0].origin && - request.args[0].portal && - request.args[0].target) { - ssb.createTunnel(request.connection.id, -request.request_number, request.args[0].origin); - } -}); - function ebtReplicateSendClock(request, have) { var identities = ssb.getAllIdentities(); var message = {}; diff --git a/src/ssb.js.c b/src/ssb.js.c index 06eec295..cd70d936 100644 --- a/src/ssb.js.c +++ b/src/ssb.js.c @@ -930,65 +930,6 @@ static JSValue _tf_ssb_hmacsha256_verify(JSContext* context, JSValueConst this_v return result; } -static JSValue _tf_ssb_createTunnel(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) -{ - tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId); - const char* portal_id = JS_ToCString(context, argv[0]); - int32_t request_number = 0; - JS_ToInt32(context, &request_number, argv[1]); - const char* target_id = JS_ToCString(context, argv[2]); - tf_ssb_connection_tunnel_create(ssb, portal_id, request_number, target_id); - JS_FreeCString(context, target_id); - JS_FreeCString(context, portal_id); - return JS_UNDEFINED; -} - -typedef struct tunnel_t -{ - tf_ssb_connection_t* connection; - int32_t request_number; -} tunnel_t; - -void _tf_ssb_tunnel_rpc_callback(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) -{ - tunnel_t* tun = user_data; - tf_ssb_connection_rpc_send(tun->connection, flags, tun->request_number, message, size, NULL, NULL, NULL); -} - -void _tf_ssb_tunnel_cleanup(tf_ssb_t* ssb, void* user_data) -{ - tf_free(user_data); -} - -static JSValue _tf_ssb_tunnel(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) -{ - tf_ssb_connection_t* connection0 = JS_GetOpaque(argv[0], tf_ssb_get_connection_class_id()); - int32_t request_number0 = 0; - JS_ToInt32(context, &request_number0, argv[1]); - - tf_ssb_connection_t* connection1 = JS_GetOpaque(argv[2], tf_ssb_get_connection_class_id()); - int32_t request_number1 = 0; - JS_ToInt32(context, &request_number1, argv[3]); - - tunnel_t* data0 = tf_malloc(sizeof(tunnel_t)); - *data0 = (tunnel_t) - { - .connection = connection1, - .request_number = request_number1, - }; - tunnel_t* data1 = tf_malloc(sizeof(tunnel_t)); - *data1 = (tunnel_t) - { - .connection = connection0, - .request_number = request_number0, - }; - - tf_ssb_connection_add_request(connection0, request_number0, _tf_ssb_tunnel_rpc_callback, _tf_ssb_tunnel_cleanup, data0, connection1); - tf_ssb_connection_add_request(connection1, request_number1, _tf_ssb_tunnel_rpc_callback, _tf_ssb_tunnel_cleanup, data1, connection0); - - return JS_UNDEFINED; -} - static JSValue _tf_ssb_connectionSendJson(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) { tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId); @@ -1054,8 +995,6 @@ void tf_ssb_register(JSContext* context, tf_ssb_t* ssb) JS_SetPropertyStr(context, object, "storeMessage", JS_NewCFunction(context, _tf_ssb_storeMessage, "storeMessage", 1)); JS_SetPropertyStr(context, object, "getBroadcasts", JS_NewCFunction(context, _tf_ssb_getBroadcasts, "getBroadcasts", 0)); JS_SetPropertyStr(context, object, "connect", JS_NewCFunction(context, _tf_ssb_connect, "connect", 1)); - JS_SetPropertyStr(context, object, "createTunnel", JS_NewCFunction(context, _tf_ssb_createTunnel, "createTunnel", 3)); - JS_SetPropertyStr(context, object, "tunnel", JS_NewCFunction(context, _tf_ssb_tunnel, "tunnel", 4)); /* Should be trusted only. */ JS_SetPropertyStr(context, object, "addRpc", JS_NewCFunction(context, _tf_ssb_add_rpc, "addRpc", 2)); diff --git a/src/ssb.rpc.c b/src/ssb.rpc.c index 47808b2a..f642674b 100644 --- a/src/ssb.rpc.c +++ b/src/ssb.rpc.c @@ -97,9 +97,118 @@ static void _tf_ssb_rpc_blobs_has(tf_ssb_connection_t* connection, uint8_t flags NULL); } +typedef struct tunnel_t +{ + tf_ssb_connection_t* connection; + int32_t request_number; +} tunnel_t; + +void _tf_ssb_rpc_tunnel_callback(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) +{ + tunnel_t* tun = user_data; + tf_ssb_connection_rpc_send(tun->connection, flags, tun->request_number, message, size, NULL, NULL, NULL); +} + +void _tf_ssb_rpc_tunnel_cleanup(tf_ssb_t* ssb, void* user_data) +{ + tf_free(user_data); +} + +static void _tf_ssb_rpc_tunnel_connect(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 arg_array = JS_GetPropertyStr(context, args, "args"); + JSValue arg = JS_GetPropertyUint32(context, arg_array, 0); + JSValue origin = JS_GetPropertyStr(context, arg, "origin"); + JSValue portal = JS_GetPropertyStr(context, arg, "portal"); + JSValue target = JS_GetPropertyStr(context, arg, "target"); + + if (JS_IsUndefined(origin) && + !JS_IsUndefined(portal) && + !JS_IsUndefined(target)) + { + const char* portal_str = JS_ToCString(context, portal); + const char* target_str = JS_ToCString(context, target); + + tf_ssb_connection_t* target_connection = tf_ssb_connection_get(ssb, target_str); + int32_t tunnel_request_number = tf_ssb_connection_next_request_number(target_connection); + + JSValue message = JS_NewObject(context); + JSValue name = JS_NewArray(context); + JS_SetPropertyUint32(context, name, 0, JS_NewString(context, "tunnel")); + JS_SetPropertyUint32(context, name, 1, JS_NewString(context, "connect")); + JS_SetPropertyStr(context, message, "name", name); + JSValue arg_obj = JS_NewObject(context); + char origin_str[k_id_base64_len] = ""; + tf_ssb_connection_get_id(connection, origin_str, sizeof(origin_str)); + JS_SetPropertyStr(context, arg_obj, "origin", JS_NewString(context, origin_str)); + JS_SetPropertyStr(context, arg_obj, "portal", JS_NewString(context, portal_str)); + JS_SetPropertyStr(context, arg_obj, "target", JS_NewString(context, target_str)); + JSValue arg_array = JS_NewArray(context); + JS_SetPropertyUint32(context, arg_array, 0, arg_obj); + JS_SetPropertyStr(context, message, "args", arg_array); + JS_SetPropertyStr(context, message, "type", JS_NewString(context, "duplex")); + JSValue message_val = JS_JSONStringify(context, message, JS_NULL, JS_NULL); + size_t size; + const char* message_str = JS_ToCStringLen(context, &size, message_val); + + tf_ssb_connection_rpc_send( + target_connection, + k_ssb_rpc_flag_json | k_ssb_rpc_flag_stream, + tunnel_request_number, + (const uint8_t*)message_str, + size, + NULL, + NULL, + NULL); + + JS_FreeCString(context, message_str); + + tunnel_t* data0 = tf_malloc(sizeof(tunnel_t)); + *data0 = (tunnel_t) + { + .connection = target_connection, + .request_number = tunnel_request_number, + }; + tunnel_t* data1 = tf_malloc(sizeof(tunnel_t)); + *data1 = (tunnel_t) + { + .connection = connection, + .request_number = -request_number, + }; + tf_ssb_connection_add_request(connection, -request_number, _tf_ssb_rpc_tunnel_callback, _tf_ssb_rpc_tunnel_cleanup, data0, connection); + tf_ssb_connection_add_request(target_connection, tunnel_request_number, _tf_ssb_rpc_tunnel_callback, _tf_ssb_rpc_tunnel_cleanup, data1, target_connection); + + JS_FreeValue(context, message_val); + JS_FreeValue(context, message); + JS_FreeCString(context, portal_str); + JS_FreeCString(context, target_str); + } + else if (!JS_IsUndefined(origin) && + !JS_IsUndefined(portal) && + !JS_IsUndefined(target)) + { + const char* origin_str = JS_ToCString(context, origin); + const char* portal_str = JS_ToCString(context, portal); + const char* target_str = JS_ToCString(context, target); + tf_ssb_connection_tunnel_create(ssb, portal_str, -request_number, origin_str); + JS_FreeCString(context, origin_str); + JS_FreeCString(context, portal_str); + JS_FreeCString(context, target_str); + } + + JS_FreeValue(context, origin); + JS_FreeValue(context, portal); + JS_FreeValue(context, target); + JS_FreeValue(context, arg); + JS_FreeValue(context, arg_array); +} + 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); + tf_ssb_add_rpc_callback(ssb, (const char*[]) { "tunnel", "connect", NULL }, _tf_ssb_rpc_tunnel_connect, NULL, NULL); }