First go at implementing rooms. A test passes that appears to exercise them.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4017 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
2022-11-02 23:34:44 +00:00
parent 1abc611e54
commit b12f8f9da8
8 changed files with 692 additions and 83 deletions

View File

@ -35,8 +35,13 @@ void tf_ssb_test_id_conversion(const tf_test_options_t* options)
typedef struct _test_t {
tf_ssb_t* ssb0;
tf_ssb_t* ssb1;
tf_ssb_t* ssb2;
int connection_count0;
int connection_count1;
int connection_count2;
int broadcast_count0;
int broadcast_count1;
int broadcast_count2;
} test_t;
static void _ssb_test_connections_changed(tf_ssb_t* ssb, tf_ssb_change_t change, tf_ssb_connection_t* connection, void* user_data)
@ -61,7 +66,12 @@ static void _ssb_test_connections_changed(tf_ssb_t* ssb, tf_ssb_change_t change,
printf("callback1 change=%d connection=%p\n", change, connection);
test->connection_count1 = count;
}
printf("conns = %d %d\n", test->connection_count0, test->connection_count1);
else if (ssb == test->ssb2)
{
printf("callback2 change=%d connection=%p\n", change, connection);
test->connection_count2 = count;
}
printf("conns = %d %d %d\n", test->connection_count0, test->connection_count1, test->connection_count2);
}
static void _count_messages_callback(JSValue row, void* user_data)
@ -240,6 +250,193 @@ void tf_ssb_test_ssb(const tf_test_options_t* options)
sqlite3_close(db1);
}
static void _broadcasts_visit(const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
{
int* count = user_data;
(*count)++;
}
static void _broadcasts_changed(tf_ssb_t* ssb, void* user_data)
{
int* count = NULL;
test_t* test = user_data;
if (ssb == test->ssb0)
{
count = &test->broadcast_count0;
}
else if (ssb == test->ssb1)
{
count = &test->broadcast_count1;
}
else if (ssb == test->ssb2)
{
count = &test->broadcast_count2;
}
*count = 0;
tf_ssb_visit_broadcasts(ssb, _broadcasts_visit, count);
printf("BROADCASTS %d %d %d\n", test->broadcast_count0, test->broadcast_count1, test->broadcast_count2);
}
void tf_ssb_test_rooms(const tf_test_options_t* options)
{
printf("Testing Rooms.\n");
sqlite3* db0 = NULL;
sqlite3* db1 = NULL;
sqlite3* db2 = NULL;
int r = sqlite3_open(":memory:", &db0);
(void)r;
assert(r == SQLITE_OK);
r = sqlite3_open(":memory:", &db1);
assert(r == SQLITE_OK);
r = sqlite3_open(":memory:", &db2);
assert(r == SQLITE_OK);
uv_loop_t loop = { 0 };
uv_loop_init(&loop);
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, db0);
tf_ssb_register(tf_ssb_get_context(ssb0), ssb0);
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, db1);
tf_ssb_register(tf_ssb_get_context(ssb1), ssb1);
tf_ssb_t* ssb2 = tf_ssb_create(&loop, NULL, db2);
tf_ssb_register(tf_ssb_get_context(ssb2), ssb2);
uv_idle_t idle0 = { .data = ssb0 };
uv_idle_init(&loop, &idle0);
uv_idle_start(&idle0, _ssb_test_idle);
uv_idle_t idle1 = { .data = ssb1 };
uv_idle_init(&loop, &idle1);
uv_idle_start(&idle1, _ssb_test_idle);
uv_idle_t idle2 = { .data = ssb2 };
uv_idle_init(&loop, &idle2);
uv_idle_start(&idle2, _ssb_test_idle);
test_t test =
{
.ssb0 = ssb0,
.ssb1 = ssb1,
.ssb2 = ssb2,
};
tf_ssb_add_connections_changed_callback(ssb0, _ssb_test_connections_changed, NULL, &test);
tf_ssb_add_connections_changed_callback(ssb1, _ssb_test_connections_changed, NULL, &test);
tf_ssb_add_connections_changed_callback(ssb2, _ssb_test_connections_changed, NULL, &test);
tf_ssb_add_broadcasts_changed_callback(ssb0, _broadcasts_changed, NULL, &test);
tf_ssb_add_broadcasts_changed_callback(ssb1, _broadcasts_changed, NULL, &test);
tf_ssb_add_broadcasts_changed_callback(ssb2, _broadcasts_changed, NULL, &test);
tf_ssb_generate_keys(ssb0);
tf_ssb_generate_keys(ssb1);
tf_ssb_generate_keys(ssb2);
char id0[k_id_base64_len] = { 0 };
char id1[k_id_base64_len] = { 0 };
char id2[k_id_base64_len] = { 0 };
bool b = tf_ssb_whoami(ssb0, id0, sizeof(id0));
(void)b;
assert(b);
b = tf_ssb_whoami(ssb1, id1, sizeof(id1));
assert(b);
b = tf_ssb_whoami(ssb2, id2, sizeof(id2));
assert(b);
printf("ID %s, %s, %s\n", id0, id1, id2);
tf_ssb_server_open(ssb0, 12347);
uint8_t id0bin[k_id_bin_len];
tf_ssb_id_str_to_bin(id0bin, id0);
tf_ssb_connect(ssb1, "127.0.0.1", 12347, id0bin);
tf_ssb_connect(ssb2, "127.0.0.1", 12347, id0bin);
printf("Waiting for connection.\n");
while (test.connection_count0 != 2 ||
test.connection_count1 != 1 ||
test.connection_count2 != 1)
{
uv_run(&loop, UV_RUN_ONCE);
}
tf_ssb_server_close(ssb0);
while (test.broadcast_count1 != 1 ||
test.broadcast_count2 != 1)
{
uv_run(&loop, UV_RUN_ONCE);
}
tf_ssb_connection_t* connections[4];
int count = tf_ssb_get_connections(ssb1, connections, 4);
assert(count == 1);
int32_t tunnel_request_number = tf_ssb_connection_next_request_number(connections[0]);
JSContext* context = tf_ssb_get_context(ssb1);
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 args = JS_NewArray(context);
JSValue arg = JS_NewObject(context);
JS_SetPropertyStr(context, arg, "portal", JS_NewString(context, id0));
JS_SetPropertyStr(context, arg, "target", JS_NewString(context, id2));
JS_SetPropertyUint32(context, args, 0, arg);
JS_SetPropertyStr(context, message, "args", args);
JS_SetPropertyStr(context, message, "type", JS_NewString(context, "duplex"));
JSValue message_json = JS_JSONStringify(context, message, JS_NULL, JS_NULL);
size_t size;
const char* raw = JS_ToCStringLen(context, &size, message_json);
tf_ssb_connection_rpc_send(
connections[0],
k_ssb_rpc_flag_json | k_ssb_rpc_flag_stream,
tunnel_request_number,
(const uint8_t*)raw,
size,
NULL,
NULL,
NULL);
JS_FreeCString(context, raw);
JS_FreeValue(context, message_json);
JS_FreeValue(context, message);
tf_ssb_connection_t* tun0 = tf_ssb_connection_tunnel_create(connections[0], tunnel_request_number, id2);
printf("tun0 = %p\n", tun0);
printf("Done.\n");
while (test.connection_count0 != 2 ||
test.connection_count1 != 2 ||
test.connection_count2 != 2)
{
uv_run(&loop, UV_RUN_ONCE);
}
printf("Done.\n");
tf_ssb_send_close(ssb1);
tf_ssb_send_close(ssb2);
uv_close((uv_handle_t*)&idle0, NULL);
uv_close((uv_handle_t*)&idle1, NULL);
uv_close((uv_handle_t*)&idle2, NULL);
uv_run(&loop, UV_RUN_DEFAULT);
tf_ssb_destroy(ssb0);
tf_ssb_destroy(ssb1);
tf_ssb_destroy(ssb2);
uv_loop_close(&loop);
sqlite3_close(db0);
sqlite3_close(db1);
sqlite3_close(db2);
}
void tf_ssb_test_following(const tf_test_options_t* options)
{
printf("Testing following.\n");