22
22
23
23
from twisted .internet import defer
24
24
25
- import synapse .server
26
- import synapse .types
25
+ from synapse import types
27
26
from synapse .api .constants import EventTypes , Membership
28
27
from synapse .api .ratelimiting import Ratelimiter
29
28
from synapse .api .errors import (
@@ -592,7 +591,7 @@ def send_membership_event(
592
591
), "Sender (%s) must be same as requester (%s)" % (sender , requester .user )
593
592
assert self .hs .is_mine (sender ), "Sender must be our own: %s" % (sender ,)
594
593
else :
595
- requester = synapse . types .create_requester (target_user )
594
+ requester = types .create_requester (target_user )
596
595
597
596
prev_event = yield self .event_creation_handler .deduplicate_state_event (
598
597
event , context
@@ -1011,21 +1010,73 @@ def __init__(self, hs):
1011
1010
self .distributor .declare ("user_joined_room" )
1012
1011
self .distributor .declare ("user_left_room" )
1013
1012
1013
+ @defer .inlineCallbacks
1014
+ def _is_remote_room_too_complex (self , room_id , remote_room_hosts ):
1015
+ """
1016
+ Check if complexity of a remote room is too great.
1017
+
1018
+ Args:
1019
+ room_id (str)
1020
+ remote_room_hosts (list[str])
1021
+
1022
+ Returns: bool of whether the complexity is too great, or None
1023
+ if unable to be fetched
1024
+ """
1025
+ max_complexity = self .hs .config .limit_remote_rooms .complexity
1026
+ complexity = yield self .federation_handler .get_room_complexity (
1027
+ remote_room_hosts , room_id
1028
+ )
1029
+
1030
+ if complexity :
1031
+ if complexity ["v1" ] > max_complexity :
1032
+ return True
1033
+ return False
1034
+ return None
1035
+
1036
+ @defer .inlineCallbacks
1037
+ def _is_local_room_too_complex (self , room_id ):
1038
+ """
1039
+ Check if the complexity of a local room is too great.
1040
+
1041
+ Args:
1042
+ room_id (str)
1043
+
1044
+ Returns: bool
1045
+ """
1046
+ max_complexity = self .hs .config .limit_remote_rooms .complexity
1047
+ complexity = yield self .store .get_room_complexity (room_id )
1048
+
1049
+ if complexity ["v1" ] > max_complexity :
1050
+ return True
1051
+
1052
+ return False
1053
+
1014
1054
@defer .inlineCallbacks
1015
1055
def _remote_join (self , requester , remote_room_hosts , room_id , user , content ):
1016
1056
"""Implements RoomMemberHandler._remote_join
1017
1057
"""
1018
1058
# filter ourselves out of remote_room_hosts: do_invite_join ignores it
1019
1059
# and if it is the only entry we'd like to return a 404 rather than a
1020
1060
# 500.
1021
-
1022
1061
remote_room_hosts = [
1023
1062
host for host in remote_room_hosts if host != self .hs .hostname
1024
1063
]
1025
1064
1026
1065
if len (remote_room_hosts ) == 0 :
1027
1066
raise SynapseError (404 , "No known servers" )
1028
1067
1068
+ if self .hs .config .limit_remote_rooms .enabled :
1069
+ # Fetch the room complexity
1070
+ too_complex = yield self ._is_remote_room_too_complex (
1071
+ room_id , remote_room_hosts
1072
+ )
1073
+ if too_complex is True :
1074
+ raise SynapseError (
1075
+ code = 400 ,
1076
+ msg = self .hs .config .limit_remote_rooms .complexity_error ,
1077
+ errcode = Codes .RESOURCE_LIMIT_EXCEEDED ,
1078
+ )
1079
+
1029
1080
# We don't do an auth check if we are doing an invite
1030
1081
# join dance for now, since we're kinda implicitly checking
1031
1082
# that we are allowed to join when we decide whether or not we
@@ -1035,6 +1086,31 @@ def _remote_join(self, requester, remote_room_hosts, room_id, user, content):
1035
1086
)
1036
1087
yield self ._user_joined_room (user , room_id )
1037
1088
1089
+ # Check the room we just joined wasn't too large, if we didn't fetch the
1090
+ # complexity of it before.
1091
+ if self .hs .config .limit_remote_rooms .enabled :
1092
+ if too_complex is False :
1093
+ # We checked, and we're under the limit.
1094
+ return
1095
+
1096
+ # Check again, but with the local state events
1097
+ too_complex = yield self ._is_local_room_too_complex (room_id )
1098
+
1099
+ if too_complex is False :
1100
+ # We're under the limit.
1101
+ return
1102
+
1103
+ # The room is too large. Leave.
1104
+ requester = types .create_requester (user , None , False , None )
1105
+ yield self .update_membership (
1106
+ requester = requester , target = user , room_id = room_id , action = "leave"
1107
+ )
1108
+ raise SynapseError (
1109
+ code = 400 ,
1110
+ msg = self .hs .config .limit_remote_rooms .complexity_error ,
1111
+ errcode = Codes .RESOURCE_LIMIT_EXCEEDED ,
1112
+ )
1113
+
1038
1114
@defer .inlineCallbacks
1039
1115
def _remote_reject_invite (self , requester , remote_room_hosts , room_id , target ):
1040
1116
"""Implements RoomMemberHandler._remote_reject_invite
0 commit comments