diff --git a/core/core.js b/core/core.js index 383222fb..db9031bd 100644 --- a/core/core.js +++ b/core/core.js @@ -23,13 +23,18 @@ const k_global_settings = { room: { type: 'boolean', default_value: true, - description: 'Whether this instance should behave as a room.', + description: 'Enable peers to tunnel through this instance as a room.', }, room_name: { type: 'string', default_value: 'tilde friends tunnel', description: 'Name of the room.', }, + replicator: { + type: 'boolean', + default_value: true, + description: 'Enable message and blob replication.', + }, code_of_conduct: { type: 'textarea', default_value: undefined, diff --git a/src/ssb.c b/src/ssb.c index 38d58b00..12087c25 100644 --- a/src/ssb.c +++ b/src/ssb.c @@ -265,6 +265,7 @@ typedef struct _tf_ssb_t uv_thread_t thread_self; bool is_room; + bool is_replicator; char* room_name; char seeds_host[256]; time_t last_seed_check; @@ -2196,6 +2197,7 @@ tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path { tf_ssb_t* ssb = tf_malloc(sizeof(tf_ssb_t)); memset(ssb, 0, sizeof(*ssb)); + ssb->is_replicator = true; const char* actual_key = network_key ? network_key : k_ssb_network_string; if (sodium_hex2bin(ssb->network_key, sizeof(ssb->network_key), actual_key, strlen(actual_key), ": ", NULL, NULL)) @@ -3997,6 +3999,16 @@ const char* tf_ssb_get_room_name(tf_ssb_t* ssb) return ssb->room_name; } +bool tf_ssb_is_replicator(tf_ssb_t* ssb) +{ + return ssb->is_replicator; +} + +void tf_ssb_set_is_replicator(tf_ssb_t* ssb, bool is_replicator) +{ + ssb->is_replicator = is_replicator; +} + void tf_ssb_set_room_name(tf_ssb_t* ssb, const char* room_name) { tf_free(ssb->room_name); diff --git a/src/ssb.h b/src/ssb.h index 2a84fac4..ab2f4cf7 100644 --- a/src/ssb.h +++ b/src/ssb.h @@ -41,6 +41,9 @@ typedef enum _tf_ssb_change_t k_tf_ssb_change_update, } tf_ssb_change_t; +/** +** The origin of a broadcast entry. +*/ typedef enum _tf_ssb_broadcast_origin_t { k_tf_ssb_broadcast_origin_discovery, @@ -972,6 +975,20 @@ bool tf_ssb_is_room(tf_ssb_t* ssb); */ void tf_ssb_set_is_room(tf_ssb_t* ssb, bool is_room); +/** +** Get whether the running server supports replication of messages and blobs. +** @param ssb The SSB instance. +** @return True if the server is a replicator. +*/ +bool tf_ssb_is_replicator(tf_ssb_t* ssb); + +/** +** Set whether the running server supports replication of messages and blobs. +** @param ssb The SSB instance. +** @param is_replicator Whether to support replication. +*/ +void tf_ssb_set_is_replicator(tf_ssb_t* ssb, bool is_replicator); + /** ** Get the name of the room hosted by the running server. ** @param ssb The SSB instance. diff --git a/src/ssb.rpc.c b/src/ssb.rpc.c index d4470cea..9f38b8cf 100644 --- a/src/ssb.rpc.c +++ b/src/ssb.rpc.c @@ -107,6 +107,12 @@ static void _tf_ssb_rpc_blobs_get(tf_ssb_connection_t* connection, uint8_t flags { return; } + tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); + if (!tf_ssb_is_replicator(ssb)) + { + tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "blobs.get"); + return; + } tf_ssb_connection_add_request(connection, -request_number, "blobs.get", _tf_ssb_rpc_blobs_get_callback, NULL, NULL, NULL); JSContext* context = tf_ssb_connection_get_context(connection); @@ -144,6 +150,11 @@ static void _tf_ssb_rpc_blobs_get(tf_ssb_connection_t* connection, uint8_t flags 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); + if (!tf_ssb_is_replicator(ssb)) + { + tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "blobs.has"); + return; + } JSContext* context = tf_ssb_connection_get_context(connection); JSValue ids = JS_GetPropertyStr(context, args, "args"); JSValue id = JS_GetPropertyUint32(context, ids, 0); @@ -242,8 +253,13 @@ static void _tf_ssb_rpc_request_more_blobs(tf_ssb_connection_t* connection) static void _tf_ssb_rpc_blobs_createWants( 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_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection); tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); + if (!tf_ssb_is_replicator(ssb)) + { + tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "blobs.createWants"); + return; + } + tf_ssb_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection); tf_ssb_add_blob_want_added_callback(ssb, _tf_ssb_rpc_blob_wants_added_callback, NULL, connection); blob_wants->request_number = request_number; _tf_ssb_rpc_request_more_blobs(connection); @@ -855,6 +871,11 @@ static void _tf_ssb_rpc_createHistoryStream( 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); + if (!tf_ssb_is_replicator(ssb)) + { + tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "createHistoryStream"); + return; + } JSContext* context = tf_ssb_get_context(ssb); JSValue arg_array = JS_GetPropertyStr(context, args, "args"); JSValue arg = JS_GetPropertyUint32(context, arg_array, 0); @@ -1157,6 +1178,12 @@ static void _tf_ssb_rpc_ebt_replicate_server( { return; } + tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); + if (!tf_ssb_is_replicator(ssb)) + { + tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "ebt.replicate"); + return; + } _tf_ssb_rpc_ebt_replicate(connection, flags, request_number, args, message, size, user_data); tf_ssb_connection_add_request(connection, -request_number, "ebt.replicate", _tf_ssb_rpc_ebt_replicate, NULL, NULL, NULL); } @@ -1189,7 +1216,10 @@ static void _tf_ssb_rpc_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_chang _tf_ssb_rpc_connection_tunnel_isRoom_callback, NULL, NULL); JS_FreeValue(context, message); - _tf_ssb_rpc_send_ebt_replicate(connection); + if (tf_ssb_is_replicator(ssb)) + { + _tf_ssb_rpc_send_ebt_replicate(connection); + } } } else if (change == k_tf_ssb_change_remove)