mirror of
https://github.com/element-hq/synapse
synced 2024-10-02 13:52:39 +00:00
Added typing, docstrings, comments
This commit is contained in:
parent
2fd7cdc1b3
commit
f73d4de691
6 changed files with 124 additions and 67 deletions
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2015, 2016 OpenMarket Ltd
|
||||
# Copyrignt 2020 Sorunome
|
||||
# Copyrignt 2020 The Matrix.org Foundation C.I.C.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -880,48 +881,51 @@ class FederationClient(FederationBase):
|
|||
# content.
|
||||
return resp[1]
|
||||
|
||||
def send_knock(self, destinations, pdu):
|
||||
"""Sends a knock event to one of a list of homeservers.
|
||||
async def send_knock(self, destinations: List[str], pdu: EventBase) -> None:
|
||||
"""Attempts to send a knock event to given a list of servers. Iterates
|
||||
through the list until one attempt succeeds.
|
||||
|
||||
Doing so will cause the remote server to add teh event to the graph,
|
||||
Doing so will cause the remote server to add the event to the graph,
|
||||
and send the event out to the rest of the federation.
|
||||
|
||||
Args:
|
||||
destinations (str): Candidate homeservers which are probably participating in the room.
|
||||
pdu (BaseEvent): event to be sent
|
||||
destinations: A list of candidate homeservers which are likely to be
|
||||
participating in the room.
|
||||
pdu: The event to be sent.
|
||||
|
||||
Return:
|
||||
Deferred: resolves to None.
|
||||
|
||||
Fails with a ``SynapseError`` if the chosen remote server
|
||||
returns a 300/400 code.
|
||||
|
||||
Fails with a ``RuntimeError`` if no servers were reachable.
|
||||
Raises:
|
||||
SynapseError: If the chosen remote server returns a 3xx/4xx code.
|
||||
RuntimeError: If no servers were reachable.
|
||||
"""
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def send_request(destination):
|
||||
content = yield self._do_send_knock(destination, pdu)
|
||||
|
||||
async def send_request(destination: str) -> None:
|
||||
content = await self._do_send_knock(destination, pdu)
|
||||
logger.debug("Got content: %s", content)
|
||||
return None
|
||||
|
||||
return self._try_destination_list("send_knock", destinations, send_request)
|
||||
return await self._try_destination_list(
|
||||
"send_knock", destinations, send_request
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _do_send_knock(self, destination, pdu):
|
||||
async def _do_send_knock(self, destination: str, pdu: EventBase) -> JsonDict:
|
||||
"""Send a knock event to a remote homeserver.
|
||||
|
||||
Args:
|
||||
destination: The homeserver to send to.
|
||||
pdu: The event to send.
|
||||
|
||||
Returns:
|
||||
The response from the remote homeserver.
|
||||
"""
|
||||
time_now = self._clock.time_msec()
|
||||
|
||||
# Only v1 exists!
|
||||
content = yield self.transport_layer.send_knock_v1(
|
||||
return await self.transport_layer.send_knock_v1(
|
||||
destination=destination,
|
||||
room_id=pdu.room_id,
|
||||
event_id=pdu.event_id,
|
||||
content=pdu.get_pdu_json(time_now),
|
||||
)
|
||||
|
||||
return content
|
||||
|
||||
def get_public_rooms(
|
||||
self,
|
||||
remote_server: str,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# Copyright 2014-2016 OpenMarket Ltd
|
||||
# Copyright 2018 New Vector Ltd
|
||||
# Copyright 2020 Sorunome
|
||||
# Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -27,6 +28,7 @@ from synapse.api.urls import (
|
|||
FEDERATION_V2_PREFIX,
|
||||
)
|
||||
from synapse.logging.utils import log_function
|
||||
from synapse.types import JsonDict
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -295,15 +297,15 @@ class TransportLayerClient:
|
|||
return response
|
||||
|
||||
@log_function
|
||||
async def send_knock_v1(self, destination, room_id, event_id, content):
|
||||
async def send_knock_v1(
|
||||
self, destination: str, room_id: str, event_id: str, content: JsonDict,
|
||||
):
|
||||
path = _create_v1_path("/send_knock/%s/%s", room_id, event_id)
|
||||
|
||||
response = await self.client.put_json(
|
||||
return await self.client.put_json(
|
||||
destination=destination, path=path, data=content
|
||||
)
|
||||
|
||||
return response
|
||||
|
||||
@log_function
|
||||
async def send_invite_v1(self, destination, room_id, event_id, content):
|
||||
path = _create_v1_path("/invite/%s/%s", room_id, event_id)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2014-2016 OpenMarket Ltd
|
||||
# Copyright 2017-2018 New Vector Ltd
|
||||
# Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||
# Copyright 2019-2020 The Matrix.org Foundation C.I.C.
|
||||
# Copyright 2020 Sorunome
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1382,31 +1382,53 @@ class FederationHandler(BaseHandler):
|
|||
return True
|
||||
|
||||
@log_function
|
||||
async def do_knock(self, target_hosts, room_id, knockee, content):
|
||||
""" Sends the knock to the remote server.
|
||||
async def do_knock(
|
||||
self, target_hosts: List[str], room_id: str, knockee: str, content: JsonDict,
|
||||
) -> Tuple[str, int]:
|
||||
"""Sends the knock to the remote server.
|
||||
|
||||
This first triggers a /make_knock/ request that returns a partial
|
||||
This first triggers a /make_knock request that returns a partial
|
||||
event that we can fill out and sign. This is then sent to the
|
||||
remote server via /send_knock/.
|
||||
remote server via /send_knock.
|
||||
|
||||
Knockees must be signed by the knockee's server before distributing.
|
||||
Knock events must be signed by the knockee's server before distributing.
|
||||
|
||||
Args:
|
||||
target_hosts: A list of hosts that we want to try knocking through.
|
||||
room_id: The ID of the room to knock on.
|
||||
knockee: The ID of the user who is knocking.
|
||||
content: The content of the knock event.
|
||||
|
||||
Returns:
|
||||
A tuple of (event ID, stream ID).
|
||||
|
||||
Raises:
|
||||
SynapseError: If the chosen remote server returns a 3xx/4xx code.
|
||||
RuntimeError: If no servers were reachable.
|
||||
"""
|
||||
logger.debug("Knocking %s to %s", knockee, room_id)
|
||||
logger.debug("Knocking on room %s on behalf of user %s", room_id, knockee)
|
||||
|
||||
# Ask the remote server to create a valid knock event for us. Once received,
|
||||
# we sign the event
|
||||
origin, event, event_format_version = await self._make_and_verify_event(
|
||||
target_hosts, room_id, knockee, "knock", content,
|
||||
)
|
||||
|
||||
# Try the host that we successfully called /make_knock/ on first for
|
||||
# the /send_knock/ request.
|
||||
# Initially try the host that we successfully called /make_knock on
|
||||
try:
|
||||
target_hosts.remove(origin)
|
||||
target_hosts.insert(0, origin)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Send the signed event back to the room
|
||||
await self.federation_client.send_knock(target_hosts, event)
|
||||
return event
|
||||
|
||||
context = await self.state_handler.compute_event_context(event)
|
||||
stream_id = await self.persist_events_and_notify(
|
||||
event.room_id, [(event, context)]
|
||||
)
|
||||
return event.event_id, stream_id
|
||||
|
||||
async def _handle_queued_pdus(self, room_queue):
|
||||
"""Process PDUs which got queued up while we were busy send_joining.
|
||||
|
|
|
@ -121,17 +121,11 @@ class RoomMemberHandler:
|
|||
|
||||
@abc.abstractmethod
|
||||
async def _remote_knock(
|
||||
self,
|
||||
requester: Requester,
|
||||
remote_room_hosts: List[str],
|
||||
room_id: str,
|
||||
user: UserID,
|
||||
content: dict,
|
||||
self, remote_room_hosts: List[str], room_id: str, user: UserID, content: dict,
|
||||
) -> Tuple[str, int]:
|
||||
"""Try and join a room that this server is not in
|
||||
|
||||
Args:
|
||||
requester
|
||||
remote_room_hosts: List of servers that can be used to knock via.
|
||||
room_id: Room that we are trying to knock on.
|
||||
user: User who is trying to knock.
|
||||
|
@ -576,7 +570,7 @@ class RoomMemberHandler:
|
|||
|
||||
elif effective_membership_state == Membership.KNOCK:
|
||||
if not is_host_in_room:
|
||||
# The knock needs to be send over federation
|
||||
# The knock needs to be sent over federation
|
||||
remote_room_hosts.append(room_id.split(":", 1)[1])
|
||||
|
||||
content["membership"] = Membership.KNOCK
|
||||
|
@ -587,12 +581,10 @@ class RoomMemberHandler:
|
|||
if "avatar_url" not in content:
|
||||
content["avatar_url"] = await profile.get_avatar_url(target)
|
||||
|
||||
remote_knock_response = await self._remote_knock(
|
||||
requester, remote_room_hosts, room_id, target, content
|
||||
return await self._remote_knock(
|
||||
remote_room_hosts, room_id, target, content
|
||||
)
|
||||
|
||||
return remote_knock_response
|
||||
|
||||
return await self._local_membership_update(
|
||||
requester=requester,
|
||||
target=target,
|
||||
|
@ -1232,7 +1224,20 @@ class RoomMemberMasterHandler(RoomMemberHandler):
|
|||
)
|
||||
return event.event_id, stream_id
|
||||
|
||||
async def _remote_knock(self, requester, remote_room_hosts, room_id, user, content):
|
||||
async def _remote_knock(
|
||||
self, remote_room_hosts: List[str], room_id: str, user: UserID, content: dict,
|
||||
) -> Tuple[str, int]:
|
||||
"""Sends a knock to a room. Attempts to do so via one remote out of a given list.
|
||||
|
||||
Args:
|
||||
remote_room_hosts: A list of homeservers to try knocking through.
|
||||
room_id: The ID of the room to knock on.
|
||||
user: The user to knock on behalf of.
|
||||
content: The content of the knock event.
|
||||
|
||||
Returns:
|
||||
A tuple of (event ID, stream ID).
|
||||
"""
|
||||
# filter ourselves out of remote_room_hosts
|
||||
remote_room_hosts = [
|
||||
host for host in remote_room_hosts if host != self.hs.hostname
|
||||
|
@ -1241,10 +1246,9 @@ class RoomMemberMasterHandler(RoomMemberHandler):
|
|||
if len(remote_room_hosts) == 0:
|
||||
raise SynapseError(404, "No known servers")
|
||||
|
||||
ret = await self.federation_handler.do_knock(
|
||||
remote_room_hosts, room_id, user.to_string(), content=content,
|
||||
return await self.federation_handler.do_knock(
|
||||
remote_room_hosts, room_id, user.to_string(), content=content
|
||||
)
|
||||
return ret
|
||||
|
||||
async def _user_left_room(self, target: UserID, room_id: str) -> None:
|
||||
"""Implements RoomMemberHandler._user_left_room
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2018 New Vector Ltd
|
||||
# Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -79,6 +80,20 @@ class RoomMemberWorkerHandler(RoomMemberHandler):
|
|||
)
|
||||
return ret["event_id"], ret["stream_id"]
|
||||
|
||||
async def _remote_knock(
|
||||
self, remote_room_hosts: List[str], room_id: str, user: UserID, content: dict,
|
||||
) -> Tuple[str, int]:
|
||||
"""Sends a knock to a room.
|
||||
|
||||
Implements RoomMemberHandler._remote_knock
|
||||
"""
|
||||
return await self._remote_knock(
|
||||
remote_room_hosts=remote_room_hosts,
|
||||
room_id=room_id,
|
||||
user=user,
|
||||
content=content,
|
||||
)
|
||||
|
||||
async def _user_left_room(self, target: UserID, room_id: str) -> None:
|
||||
"""Implements RoomMemberHandler._user_left_room
|
||||
"""
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2020 Sorunome
|
||||
# Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -12,14 +13,19 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, List, Optional, Tuple
|
||||
|
||||
from twisted.web.server import Request
|
||||
|
||||
from synapse.api.errors import SynapseError
|
||||
from synapse.http.servlet import RestServlet, parse_json_object_from_request
|
||||
from synapse.logging.opentracing import set_tag
|
||||
from synapse.rest.client.transactions import HttpTransactionCache
|
||||
from synapse.types import RoomAlias, RoomID
|
||||
from synapse.types import JsonDict, RoomAlias, RoomID
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from synapse.app.homeserver import HomeServer
|
||||
|
||||
from ._base import client_patterns
|
||||
|
||||
|
@ -27,7 +33,7 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class TransactionRestServlet(RestServlet):
|
||||
def __init__(self, hs):
|
||||
def __init__(self, hs: "HomeServer"):
|
||||
super(TransactionRestServlet, self).__init__()
|
||||
self.txns = HttpTransactionCache(hs)
|
||||
|
||||
|
@ -39,12 +45,14 @@ class KnockServlet(TransactionRestServlet):
|
|||
|
||||
PATTERNS = client_patterns("/rooms/(?P<room_id>[^/]*)/knock")
|
||||
|
||||
def __init__(self, hs):
|
||||
super(KnockServlet, self).__init__(hs)
|
||||
def __init__(self, hs: "HomeServer"):
|
||||
super().__init__(hs)
|
||||
self.room_member_handler = hs.get_room_member_handler()
|
||||
self.auth = hs.get_auth()
|
||||
|
||||
async def on_POST(self, request, room_id, txn_id=None):
|
||||
async def on_POST(
|
||||
self, request: Request, room_id: str, txn_id: Optional[str] = None
|
||||
):
|
||||
requester = await self.auth.get_user_by_req(request)
|
||||
|
||||
content = parse_json_object_from_request(request)
|
||||
|
@ -64,7 +72,7 @@ class KnockServlet(TransactionRestServlet):
|
|||
|
||||
return 200, {}
|
||||
|
||||
def on_PUT(self, request, room_id, txn_id):
|
||||
def on_PUT(self, request: Request, room_id: str, txn_id: str):
|
||||
set_tag("txn_id", txn_id)
|
||||
|
||||
return self.txns.fetch_or_execute_request(
|
||||
|
@ -79,12 +87,14 @@ class KnockRoomAliasServlet(TransactionRestServlet):
|
|||
|
||||
PATTERNS = client_patterns("/knock/(?P<room_identifier>[^/]*)")
|
||||
|
||||
def __init__(self, hs):
|
||||
super(KnockRoomAliasServlet, self).__init__(hs)
|
||||
def __init__(self, hs: "HomeServer"):
|
||||
super().__init__(hs)
|
||||
self.room_member_handler = hs.get_room_member_handler()
|
||||
self.auth = hs.get_auth()
|
||||
|
||||
async def on_POST(self, request, room_identifier, txn_id=None):
|
||||
async def on_POST(
|
||||
self, request: Request, room_identifier: str, txn_id: Optional[str] = None,
|
||||
) -> Tuple[int, JsonDict]:
|
||||
requester = await self.auth.get_user_by_req(request)
|
||||
|
||||
content = parse_json_object_from_request(request)
|
||||
|
@ -97,14 +107,14 @@ class KnockRoomAliasServlet(TransactionRestServlet):
|
|||
try:
|
||||
remote_room_hosts = [
|
||||
x.decode("ascii") for x in request.args[b"server_name"]
|
||||
]
|
||||
] # type: Optional[List[str]]
|
||||
except Exception:
|
||||
remote_room_hosts = None
|
||||
elif RoomAlias.is_valid(room_identifier):
|
||||
handler = self.room_member_handler
|
||||
room_alias = RoomAlias.from_string(room_identifier)
|
||||
room_id, remote_room_hosts = await handler.lookup_room_alias(room_alias)
|
||||
room_id = room_id.to_string()
|
||||
room_id_obj, remote_room_hosts = await handler.lookup_room_alias(room_alias)
|
||||
room_id = room_id_obj.to_string()
|
||||
else:
|
||||
raise SynapseError(
|
||||
400, "%s was not legal room ID or room alias" % (room_identifier,)
|
||||
|
@ -123,7 +133,7 @@ class KnockRoomAliasServlet(TransactionRestServlet):
|
|||
|
||||
return 200, {}
|
||||
|
||||
def on_PUT(self, request, room_identifier, txn_id):
|
||||
def on_PUT(self, request: Request, room_identifier: str, txn_id: str):
|
||||
set_tag("txn_id", txn_id)
|
||||
|
||||
return self.txns.fetch_or_execute_request(
|
||||
|
|
Loading…
Reference in a new issue