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
{
const char** name;
const char* flattened_name;
const char* name;
tf_ssb_rpc_callback_t* callback;
tf_ssb_callback_cleanup_t* cleanup;
void* user_data;
@ -1521,60 +1520,28 @@ static bool _tf_ssb_connection_recv_pop(tf_ssb_connection_t* connection, uint8_t
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");
if (JS_IsArray(context, name))
{
int length = tf_util_get_length(context, name);
int offset = 0;
for (int i = 0; i < length; i++)
{
if (!match[i])
{
result = false;
break;
}
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;
JSValue part = JS_GetPropertyUint32(context, name, i);
const char* part_str = JS_ToCString(context, part);
offset += snprintf(buffer + offset, size - offset, "%s%s", i == 0 ? "" : ".", part_str);
JS_FreeCString(context, part_str);
JS_FreeValue(context, part);
}
}
else if (JS_IsString(name))
{
/* Manifest is traditionally sent as not an array for some reason. */
const char* str = JS_ToCString(context, name);
result = str && match[0] && strcmp(str, match[0]) == 0 && !match[1];
JS_FreeCString(context, str);
const char* part_str = JS_ToCString(context, name);
snprintf(buffer, size, "%s", part_str);
JS_FreeCString(context, part_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);
}
@ -1624,35 +1591,14 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
else if (JS_IsObject(val))
{
bool found = false;
char namebuf[256] = "";
JSValue name = JS_GetPropertyStr(context, val, "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);
char name[256] = "";
_tf_ssb_name_to_string(context, val, name, sizeof(name));
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_trace_begin(connection->ssb->trace, it->flattened_name);
tf_ssb_connection_add_request(connection, -request_number, name, NULL, NULL, NULL, NULL);
tf_trace_begin(connection->ssb->trace, it->name);
PRE_CALLBACK(connection->ssb, it->callback);
it->callback(connection, flags, request_number, val, message, size, it->user_data);
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;
}
}
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);
char buffer[256];
_tf_ssb_name_to_string(context, val, buffer, sizeof(buffer));
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, buffer);
tf_ssb_connection_add_request(connection, -request_number, name, NULL, NULL, NULL, NULL);
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, name);
}
}
}
@ -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;
int name_count = 0;
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);
size_t name_len = strlen(name);
tf_ssb_rpc_callback_node_t* node = tf_malloc(sizeof(tf_ssb_rpc_callback_node_t) + name_len + 1);
*node = (tf_ssb_rpc_callback_node_t) {
.name = (const char**)(node + 1),
.flattened_name = (const char*)(node + 1) + (name_count + 1) * sizeof(const char*) + name_len,
.name = (const char*)(node + 1),
.callback = callback,
.cleanup = cleanup,
.user_data = user_data,
.next = ssb->rpc,
};
char* p = (char*)(node + 1) + (name_count + 1) * sizeof(const char*);
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;
memcpy((char*)node->name, name, name_len + 1);
ssb->rpc = node;
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.
** @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 cleanup A function to be called when the callback is removed.
** @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.

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)
{
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, (const char*[]) { "blobs", "get", NULL }, _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, (const char*[]) { "blobs", "createWants", NULL }, _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, (const char*[]) { "tunnel", "isRoom", NULL }, _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, (const char*[]) { "room", "attendants", NULL }, _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, (const char*[]) { "ebt", "replicate", NULL }, _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, "gossip.ping", _tf_ssb_rpc_gossip_ping, NULL, NULL); /* DUPLEX */
tf_ssb_add_rpc_callback(ssb, "blobs.get", _tf_ssb_rpc_blobs_get, NULL, NULL); /* SOURCE */
tf_ssb_add_rpc_callback(ssb, "blobs.has", _tf_ssb_rpc_blobs_has, NULL, NULL); /* ASYNC */
tf_ssb_add_rpc_callback(ssb, "blobs.createWants", _tf_ssb_rpc_blobs_createWants, NULL, NULL); /* SOURCE */
tf_ssb_add_rpc_callback(ssb, "tunnel.connect", _tf_ssb_rpc_tunnel_connect, NULL, NULL); /* DUPLEX */
tf_ssb_add_rpc_callback(ssb, "tunnel.isRoom", _tf_ssb_rpc_room_meta, NULL, NULL); /* FAKE-ASYNC */
tf_ssb_add_rpc_callback(ssb, "room.metadata", _tf_ssb_rpc_room_meta, NULL, NULL); /* ASYNC */
tf_ssb_add_rpc_callback(ssb, "room.attendants", _tf_ssb_rpc_room_attendants, NULL, NULL); /* SOURCE */
tf_ssb_add_rpc_callback(ssb, "createHistoryStream", _tf_ssb_rpc_createHistoryStream, NULL, NULL); /* SOURCE */
tf_ssb_add_rpc_callback(ssb, "ebt.replicate", _tf_ssb_rpc_ebt_replicate_server, NULL, NULL); /* DUPLEX */
tf_ssb_add_rpc_callback(ssb, "peers.exchange", _tf_ssb_rpc_peers_exchange, NULL, NULL); /* ASYNC */
}