forked from cory/tildefriends
muxrpc: Simplifying comparing RPC names. This has just always bugged me.
This commit is contained in:
parent
8e1ad6b16a
commit
681859531c
133
src/ssb.c
133
src/ssb.c
@ -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++;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user