muxrpc: Simplifying comparing RPC names. This has just always bugged me.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled

This commit is contained in:
Cory McWilliams 2024-10-02 18:46:12 -04:00
parent 8e1ad6b16a
commit 681859531c
3 changed files with 37 additions and 122 deletions

133
src/ssb.c
View File

@ -131,8 +131,7 @@ typedef struct _tf_ssb_broadcast_t
typedef struct _tf_ssb_rpc_callback_node_t tf_ssb_rpc_callback_node_t; typedef struct _tf_ssb_rpc_callback_node_t tf_ssb_rpc_callback_node_t;
typedef struct _tf_ssb_rpc_callback_node_t typedef struct _tf_ssb_rpc_callback_node_t
{ {
const char** name; const char* name;
const char* flattened_name;
tf_ssb_rpc_callback_t* callback; tf_ssb_rpc_callback_t* callback;
tf_ssb_callback_cleanup_t* cleanup; tf_ssb_callback_cleanup_t* cleanup;
void* user_data; void* user_data;
@ -1521,60 +1520,28 @@ static bool _tf_ssb_connection_recv_pop(tf_ssb_connection_t* connection, uint8_t
return true; return true;
} }
static bool _tf_ssb_name_equals(JSContext* context, JSValue object, const char** match) static void _tf_ssb_name_to_string(JSContext* context, JSValue object, char* buffer, size_t size)
{ {
bool result = true;
JSValue name = JS_GetPropertyStr(context, object, "name"); JSValue name = JS_GetPropertyStr(context, object, "name");
if (JS_IsArray(context, name)) if (JS_IsArray(context, name))
{ {
int length = tf_util_get_length(context, name); int length = tf_util_get_length(context, name);
int offset = 0;
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
if (!match[i]) JSValue part = JS_GetPropertyUint32(context, name, i);
{ const char* part_str = JS_ToCString(context, part);
result = false; offset += snprintf(buffer + offset, size - offset, "%s%s", i == 0 ? "" : ".", part_str);
break; JS_FreeCString(context, part_str);
} JS_FreeValue(context, part);
JSValue element = JS_GetPropertyUint32(context, name, i);
const char* str = JS_ToCString(context, element);
if (!str || strcmp(str, match[i]) != 0)
{
result = false;
}
JS_FreeCString(context, str);
JS_FreeValue(context, element);
}
if (result && match[length])
{
result = false;
} }
} }
else if (JS_IsString(name)) else if (JS_IsString(name))
{ {
/* Manifest is traditionally sent as not an array for some reason. */ const char* part_str = JS_ToCString(context, name);
const char* str = JS_ToCString(context, name); snprintf(buffer, size, "%s", part_str);
result = str && match[0] && strcmp(str, match[0]) == 0 && !match[1]; JS_FreeCString(context, part_str);
JS_FreeCString(context, str);
} }
else
{
result = false;
}
JS_FreeValue(context, name);
return result;
}
static void _tf_ssb_name_to_string(JSContext* context, JSValue object, char* buffer, size_t size)
{
JSValue name = JS_GetPropertyStr(context, object, "name");
JSValue json_val = JS_JSONStringify(context, name, JS_NULL, JS_NewInt32(context, 2));
const char* value = JS_ToCString(context, json_val);
snprintf(buffer, size, "%s", value);
JS_FreeCString(context, value);
JS_FreeValue(context, json_val);
JS_FreeValue(context, name); JS_FreeValue(context, name);
} }
@ -1624,35 +1591,14 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
else if (JS_IsObject(val)) else if (JS_IsObject(val))
{ {
bool found = false; bool found = false;
char namebuf[256] = ""; char name[256] = "";
JSValue name = JS_GetPropertyStr(context, val, "name"); _tf_ssb_name_to_string(context, val, name, sizeof(name));
if (JS_IsArray(context, name))
{
int length = tf_util_get_length(context, name);
int offset = 0;
for (int i = 0; i < length; i++)
{
JSValue part = JS_GetPropertyUint32(context, name, i);
const char* part_str = JS_ToCString(context, part);
offset += snprintf(namebuf + offset, sizeof(namebuf) - offset, "%s%s", i == 0 ? "" : ".", part_str);
JS_FreeCString(context, part_str);
JS_FreeValue(context, part);
}
}
else if (JS_IsString(name))
{
const char* part_str = JS_ToCString(context, name);
snprintf(namebuf, sizeof(namebuf), "%s", part_str);
JS_FreeCString(context, part_str);
}
JS_FreeValue(context, name);
for (tf_ssb_rpc_callback_node_t* it = connection->ssb->rpc; it; it = it->next) for (tf_ssb_rpc_callback_node_t* it = connection->ssb->rpc; it; it = it->next)
{ {
if (_tf_ssb_name_equals(context, val, it->name)) if (strcmp(name, it->name) == 0)
{ {
tf_ssb_connection_add_request(connection, -request_number, namebuf, NULL, NULL, NULL, NULL); tf_ssb_connection_add_request(connection, -request_number, name, NULL, NULL, NULL, NULL);
tf_trace_begin(connection->ssb->trace, it->flattened_name); tf_trace_begin(connection->ssb->trace, it->name);
PRE_CALLBACK(connection->ssb, it->callback); PRE_CALLBACK(connection->ssb, it->callback);
it->callback(connection, flags, request_number, val, message, size, it->user_data); it->callback(connection, flags, request_number, val, message, size, it->user_data);
POST_CALLBACK(connection->ssb, it->callback); POST_CALLBACK(connection->ssb, it->callback);
@ -1661,12 +1607,10 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
break; break;
} }
} }
if (!found && !_tf_ssb_name_equals(context, val, (const char*[]) { "Error", NULL })) if (!found && strcmp(name, "Error") != 0)
{ {
tf_ssb_connection_add_request(connection, -request_number, namebuf, NULL, NULL, NULL, NULL); tf_ssb_connection_add_request(connection, -request_number, name, NULL, NULL, NULL, NULL);
char buffer[256]; tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, name);
_tf_ssb_name_to_string(context, val, buffer, sizeof(buffer));
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, buffer);
} }
} }
} }
@ -3479,47 +3423,18 @@ void tf_ssb_remove_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_connection
} }
} }
void tf_ssb_add_rpc_callback(tf_ssb_t* ssb, const char** name, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data) void tf_ssb_add_rpc_callback(tf_ssb_t* ssb, const char* name, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data)
{ {
size_t name_len = 0; size_t name_len = strlen(name);
int name_count = 0; tf_ssb_rpc_callback_node_t* node = tf_malloc(sizeof(tf_ssb_rpc_callback_node_t) + name_len + 1);
for (int i = 0; name[i]; i++)
{
name_count++;
name_len += strlen(name[i]) + 1;
}
tf_ssb_rpc_callback_node_t* node = tf_malloc(sizeof(tf_ssb_rpc_callback_node_t) + (name_count + 1) * sizeof(const char*) + name_len + name_len + 3);
*node = (tf_ssb_rpc_callback_node_t) { *node = (tf_ssb_rpc_callback_node_t) {
.name = (const char**)(node + 1), .name = (const char*)(node + 1),
.flattened_name = (const char*)(node + 1) + (name_count + 1) * sizeof(const char*) + name_len,
.callback = callback, .callback = callback,
.cleanup = cleanup, .cleanup = cleanup,
.user_data = user_data, .user_data = user_data,
.next = ssb->rpc, .next = ssb->rpc,
}; };
char* p = (char*)(node + 1) + (name_count + 1) * sizeof(const char*); memcpy((char*)node->name, name, name_len + 1);
for (int i = 0; i < name_count; i++)
{
size_t len = strlen(name[i]);
memcpy(p, name[i], len + 1);
node->name[i] = p;
p += len + 1;
}
char* flattened_name = (char*)node->flattened_name;
for (int i = 0; i < name_count; i++)
{
size_t length = strlen(name[i]);
memcpy(flattened_name, name[i], length);
flattened_name += length;
if (i != name_count - 1)
{
*flattened_name++ = '.';
}
}
*flattened_name++ = '(';
*flattened_name++ = ')';
*flattened_name++ = '\0';
node->name[name_count] = NULL;
ssb->rpc = node; ssb->rpc = node;
ssb->rpc_count++; ssb->rpc_count++;
} }

View File

@ -676,12 +676,12 @@ typedef void(tf_ssb_rpc_callback_t)(tf_ssb_connection_t* connection, uint8_t fla
/** /**
** Register a MUXRPC callback by name. ** Register a MUXRPC callback by name.
** @param ssb The SSB instance. ** @param ssb The SSB instance.
** @param name The NULL-terminated name. ** @param name The RPC name as a .-separated string.
** @param callback The callback. ** @param callback The callback.
** @param cleanup A function to be called when the callback is removed. ** @param cleanup A function to be called when the callback is removed.
** @param user_data User data to pass to the callback. ** @param user_data User data to pass to the callback.
*/ */
void tf_ssb_add_rpc_callback(tf_ssb_t* ssb, const char** name, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data); void tf_ssb_add_rpc_callback(tf_ssb_t* ssb, const char* name, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data);
/** /**
** Remove a MUXRPC callback. ** Remove a MUXRPC callback.

View File

@ -1511,15 +1511,15 @@ static void _tf_ssb_rpc_peers_exchange(tf_ssb_connection_t* connection, uint8_t
void tf_ssb_rpc_register(tf_ssb_t* ssb) void tf_ssb_rpc_register(tf_ssb_t* ssb)
{ {
tf_ssb_add_connections_changed_callback(ssb, _tf_ssb_rpc_connections_changed_callback, NULL, NULL); tf_ssb_add_connections_changed_callback(ssb, _tf_ssb_rpc_connections_changed_callback, NULL, NULL);
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "gossip", "ping", NULL }, _tf_ssb_rpc_gossip_ping, NULL, NULL); /* DUPLEX */ tf_ssb_add_rpc_callback(ssb, "gossip.ping", _tf_ssb_rpc_gossip_ping, NULL, NULL); /* DUPLEX */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "blobs", "get", NULL }, _tf_ssb_rpc_blobs_get, NULL, NULL); /* SOURCE */ tf_ssb_add_rpc_callback(ssb, "blobs.get", _tf_ssb_rpc_blobs_get, NULL, NULL); /* SOURCE */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "blobs", "has", NULL }, _tf_ssb_rpc_blobs_has, NULL, NULL); /* ASYNC */ tf_ssb_add_rpc_callback(ssb, "blobs.has", _tf_ssb_rpc_blobs_has, NULL, NULL); /* ASYNC */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "blobs", "createWants", NULL }, _tf_ssb_rpc_blobs_createWants, NULL, NULL); /* SOURCE */ tf_ssb_add_rpc_callback(ssb, "blobs.createWants", _tf_ssb_rpc_blobs_createWants, NULL, NULL); /* SOURCE */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "tunnel", "connect", NULL }, _tf_ssb_rpc_tunnel_connect, NULL, NULL); /* DUPLEX */ tf_ssb_add_rpc_callback(ssb, "tunnel.connect", _tf_ssb_rpc_tunnel_connect, NULL, NULL); /* DUPLEX */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "tunnel", "isRoom", NULL }, _tf_ssb_rpc_room_meta, NULL, NULL); /* FAKE-ASYNC */ tf_ssb_add_rpc_callback(ssb, "tunnel.isRoom", _tf_ssb_rpc_room_meta, NULL, NULL); /* FAKE-ASYNC */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "room", "metadata", NULL }, _tf_ssb_rpc_room_meta, NULL, NULL); /* ASYNC */ tf_ssb_add_rpc_callback(ssb, "room.metadata", _tf_ssb_rpc_room_meta, NULL, NULL); /* ASYNC */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "room", "attendants", NULL }, _tf_ssb_rpc_room_attendants, NULL, NULL); /* SOURCE */ tf_ssb_add_rpc_callback(ssb, "room.attendants", _tf_ssb_rpc_room_attendants, NULL, NULL); /* SOURCE */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "createHistoryStream", NULL }, _tf_ssb_rpc_createHistoryStream, NULL, NULL); /* SOURCE */ tf_ssb_add_rpc_callback(ssb, "createHistoryStream", _tf_ssb_rpc_createHistoryStream, NULL, NULL); /* SOURCE */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "ebt", "replicate", NULL }, _tf_ssb_rpc_ebt_replicate_server, NULL, NULL); /* DUPLEX */ tf_ssb_add_rpc_callback(ssb, "ebt.replicate", _tf_ssb_rpc_ebt_replicate_server, NULL, NULL); /* DUPLEX */
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "peers", "exchange", NULL }, _tf_ssb_rpc_peers_exchange, NULL, NULL); /* ASYNC */ tf_ssb_add_rpc_callback(ssb, "peers.exchange", _tf_ssb_rpc_peers_exchange, NULL, NULL); /* ASYNC */
} }