1
- # Copyright 2014-2021 The Matrix.org Foundation C.I.C.
1
+ # Copyright 2014-2022 The Matrix.org Foundation C.I.C.
2
2
# Copyright 2020 Sorunome
3
3
#
4
4
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -60,6 +60,7 @@ class TransportLayerClient:
60
60
def __init__ (self , hs ):
61
61
self .server_name = hs .hostname
62
62
self .client = hs .get_federation_http_client ()
63
+ self ._faster_joins_enabled = hs .config .experimental .faster_joins_enabled
63
64
64
65
async def get_room_state_ids (
65
66
self , destination : str , room_id : str , event_id : str
@@ -336,10 +337,15 @@ async def send_join_v2(
336
337
content : JsonDict ,
337
338
) -> "SendJoinResponse" :
338
339
path = _create_v2_path ("/send_join/%s/%s" , room_id , event_id )
340
+ query_params : Dict [str , str ] = {}
341
+ if self ._faster_joins_enabled :
342
+ # lazy-load state on join
343
+ query_params ["org.matrix.msc3706.partial_state" ] = "true"
339
344
340
345
return await self .client .put_json (
341
346
destination = destination ,
342
347
path = path ,
348
+ args = query_params ,
343
349
data = content ,
344
350
parser = SendJoinParser (room_version , v1_api = False ),
345
351
max_response_size = MAX_RESPONSE_SIZE_SEND_JOIN ,
@@ -1271,6 +1277,12 @@ class SendJoinResponse:
1271
1277
# "event" is not included in the response.
1272
1278
event : Optional [EventBase ] = None
1273
1279
1280
+ # The room state is incomplete
1281
+ partial_state : bool = False
1282
+
1283
+ # List of servers in the room
1284
+ servers_in_room : Optional [List [str ]] = None
1285
+
1274
1286
1275
1287
@ijson .coroutine
1276
1288
def _event_parser (event_dict : JsonDict ) -> Generator [None , Tuple [str , Any ], None ]:
@@ -1297,6 +1309,32 @@ def _event_list_parser(
1297
1309
events .append (event )
1298
1310
1299
1311
1312
+ @ijson .coroutine
1313
+ def _partial_state_parser (response : SendJoinResponse ) -> Generator [None , Any , None ]:
1314
+ """Helper function for use with `ijson.items_coro`
1315
+
1316
+ Parses the partial_state field in send_join responses
1317
+ """
1318
+ while True :
1319
+ val = yield
1320
+ if not isinstance (val , bool ):
1321
+ raise TypeError ("partial_state must be a boolean" )
1322
+ response .partial_state = val
1323
+
1324
+
1325
+ @ijson .coroutine
1326
+ def _servers_in_room_parser (response : SendJoinResponse ) -> Generator [None , Any , None ]:
1327
+ """Helper function for use with `ijson.items_coro`
1328
+
1329
+ Parses the servers_in_room field in send_join responses
1330
+ """
1331
+ while True :
1332
+ val = yield
1333
+ if not isinstance (val , list ) or any (not isinstance (x , str ) for x in val ):
1334
+ raise TypeError ("servers_in_room must be a list of strings" )
1335
+ response .servers_in_room = val
1336
+
1337
+
1300
1338
class SendJoinParser (ByteParser [SendJoinResponse ]):
1301
1339
"""A parser for the response to `/send_join` requests.
1302
1340
@@ -1308,44 +1346,62 @@ class SendJoinParser(ByteParser[SendJoinResponse]):
1308
1346
CONTENT_TYPE = "application/json"
1309
1347
1310
1348
def __init__ (self , room_version : RoomVersion , v1_api : bool ):
1311
- self ._response = SendJoinResponse ([], [], {})
1349
+ self ._response = SendJoinResponse ([], [], event_dict = {})
1312
1350
self ._room_version = room_version
1351
+ self ._coros = []
1313
1352
1314
1353
# The V1 API has the shape of `[200, {...}]`, which we handle by
1315
1354
# prefixing with `item.*`.
1316
1355
prefix = "item." if v1_api else ""
1317
1356
1318
- self ._coro_state = ijson .items_coro (
1319
- _event_list_parser (room_version , self ._response .state ),
1320
- prefix + "state.item" ,
1321
- use_float = True ,
1322
- )
1323
- self ._coro_auth = ijson .items_coro (
1324
- _event_list_parser (room_version , self ._response .auth_events ),
1325
- prefix + "auth_chain.item" ,
1326
- use_float = True ,
1327
- )
1328
- # TODO Remove the unstable prefix when servers have updated.
1329
- #
1330
- # By re-using the same event dictionary this will cause the parsing of
1331
- # org.matrix.msc3083.v2.event and event to stomp over each other.
1332
- # Generally this should be fine.
1333
- self ._coro_unstable_event = ijson .kvitems_coro (
1334
- _event_parser (self ._response .event_dict ),
1335
- prefix + "org.matrix.msc3083.v2.event" ,
1336
- use_float = True ,
1337
- )
1338
- self ._coro_event = ijson .kvitems_coro (
1339
- _event_parser (self ._response .event_dict ),
1340
- prefix + "event" ,
1341
- use_float = True ,
1342
- )
1357
+ self ._coros = [
1358
+ ijson .items_coro (
1359
+ _event_list_parser (room_version , self ._response .state ),
1360
+ prefix + "state.item" ,
1361
+ use_float = True ,
1362
+ ),
1363
+ ijson .items_coro (
1364
+ _event_list_parser (room_version , self ._response .auth_events ),
1365
+ prefix + "auth_chain.item" ,
1366
+ use_float = True ,
1367
+ ),
1368
+ # TODO Remove the unstable prefix when servers have updated.
1369
+ #
1370
+ # By re-using the same event dictionary this will cause the parsing of
1371
+ # org.matrix.msc3083.v2.event and event to stomp over each other.
1372
+ # Generally this should be fine.
1373
+ ijson .kvitems_coro (
1374
+ _event_parser (self ._response .event_dict ),
1375
+ prefix + "org.matrix.msc3083.v2.event" ,
1376
+ use_float = True ,
1377
+ ),
1378
+ ijson .kvitems_coro (
1379
+ _event_parser (self ._response .event_dict ),
1380
+ prefix + "event" ,
1381
+ use_float = True ,
1382
+ ),
1383
+ ]
1384
+
1385
+ if not v1_api :
1386
+ self ._coros .append (
1387
+ ijson .items_coro (
1388
+ _partial_state_parser (self ._response ),
1389
+ "org.matrix.msc3706.partial_state" ,
1390
+ use_float = "True" ,
1391
+ )
1392
+ )
1393
+
1394
+ self ._coros .append (
1395
+ ijson .items_coro (
1396
+ _servers_in_room_parser (self ._response ),
1397
+ "org.matrix.msc3706.servers_in_room" ,
1398
+ use_float = "True" ,
1399
+ )
1400
+ )
1343
1401
1344
1402
def write (self , data : bytes ) -> int :
1345
- self ._coro_state .send (data )
1346
- self ._coro_auth .send (data )
1347
- self ._coro_unstable_event .send (data )
1348
- self ._coro_event .send (data )
1403
+ for c in self ._coros :
1404
+ c .send (data )
1349
1405
1350
1406
return len (data )
1351
1407
0 commit comments