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

@ -1,6 +1,7 @@
"use strict";
var g_wants_requests = {};
var g_database = new Database('core');
let g_attendants = {};
const k_use_create_history_stream = false;
const k_blobs_concurrent_target = 8;
@ -72,7 +73,28 @@ function storeMessage(message) {
}
}
ssb.addEventListener('connections', function(change, connection) {
function tunnel_attendants(request) {
if (request.message.type !== 'state') {
throw Error('Unexpected type: ' + request.message.type);
}
let state = new Set(request.message.ids);
for (let id of state) {
request.add_room_attendant(id);
}
request.more(function attendants(message) {
if (message.message.type === 'joined') {
request.add_room_attendant(message.message.id);
state.add(message.message.id);
} else if (message.message.type === 'left') {
request.remove_room_attendant(message.message.id);
state.delete(message.message.id);
} else {
throw Error('Unexpected type: ' + message.type);
}
});
}
ssb.addEventListener('connections', function on_connections_changed(change, connection) {
if (change == 'add') {
var sequence = get_latest_sequence_for_author(connection.id);
if (k_use_create_history_stream) {
@ -89,12 +111,17 @@ ssb.addEventListener('connections', function(change, connection) {
});
} else {
if (connection.is_client) {
connection.send_json({'name': ['tunnel', 'isRoom'], 'args': [], 'type': 'source'}, function tunnel_is_room(request) {
if (request.message) {
connection.send_json({'name': ['room', 'attendants'], 'args': [], 'type': 'source'}, tunnel_attendants);
}
});
connection.send_json({"name": ["ebt", "replicate"], "args": [{"version": 3, "format": "classic"}], "type": "duplex"}, ebtReplicateClient);
}
}
connection.active_blob_wants = {};
connection.send_json({'name': ['blobs', 'createWants'], 'type': 'source', 'args': []}, function(message) {
connection.send_json({'name': ['blobs', 'createWants'], 'type': 'source', 'args': []}, function on_blob_create_wants(message) {
Object.keys(message.message).forEach(function(id) {
if (message.message[id] < 0) {
if (g_wants_requests[connection.id]) {
@ -129,6 +156,8 @@ ssb.addEventListener('connections', function(change, connection) {
});
} else if (change == 'remove') {
print('REMOVE', connection.id);
notify_attendant_changed(connection.id, 'left');
delete g_attendants[connection.id];
delete g_wants_requests[connection.id];
} else {
print('CHANGE', change);
@ -191,13 +220,59 @@ ssb.addRpc(['blobs', 'get'], function(request) {
});
ssb.addRpc(['gossip', 'ping'], function(request) {
request.more(function(message) {
request.more(function ping(message) {
message.send_json(Date.now());
});
});
ssb.addRpc(['tunnel', 'isRoom'], function(request) {
request.send_json(false);
request.send_json(true);
});
function notify_attendant_changed(id, type) {
for (let r of Object.values(g_attendants)) {
try {
r.send_json({
type: type,
id: id,
});
} catch (e) {
print(`Removing ${r.connection.id} from g_attendants in ${type}.`, e);
delete g_attendants[r.connection.id];
}
}
}
ssb.addRpc(['room', 'attendants'], function(request) {
let ids = Object.keys(g_attendants).sort();
request.send_json({
type: 'state',
ids: ids,
});
notify_attendant_changed(request.connection.id, 'joined');
g_attendants[request.connection.id] = request;
});
ssb.addRpc(['tunnel', 'connect'], function(request) {
if (!request.args[0].origin &&
request.args[0].portal &&
request.args[0].target) {
let target_connection = ssb.getConnection(request.args[0].target);
let target_request_number = target_connection.send_json({
'name': ['tunnel', 'connect'],
'args': [{
'origin': request.connection.id,
'portal': request.args[0].portal,
'target': request.args[0].target,
}],
'type': 'duplex',
});
ssb.tunnel(request.connection, -request.request_number, target_connection, target_request_number);
} else if (request.args[0].origin &&
request.args[0].portal &&
request.args[0].target) {
ssb.createTunnel(request.connection, -request.request_number, request.args[0].origin);
}
});
function ebtReplicateSendClock(request, have) {