123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- # -*- coding: utf-8 -*-
- # Copyright 2014, 2015 OpenMarket Ltd
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # 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.
- from twisted.internet import defer
- from synapse.api.constants import Membership
- from synapse.api.urls import FEDERATION_PREFIX as PREFIX
- from synapse.util.logutils import log_function
- import logging
- logger = logging.getLogger(__name__)
- class TransportLayerClient(object):
- """Sends federation HTTP requests to other servers"""
- @log_function
- def get_room_state(self, destination, room_id, event_id):
- """ Requests all state for a given room from the given server at the
- given event.
- Args:
- destination (str): The host name of the remote home server we want
- to get the state from.
- context (str): The name of the context we want the state of
- event_id (str): The event we want the context at.
- Returns:
- Deferred: Results in a dict received from the remote homeserver.
- """
- logger.debug("get_room_state dest=%s, room=%s",
- destination, room_id)
- path = PREFIX + "/state/%s/" % room_id
- return self.client.get_json(
- destination, path=path, args={"event_id": event_id},
- )
- @log_function
- def get_event(self, destination, event_id, timeout=None):
- """ Requests the pdu with give id and origin from the given server.
- Args:
- destination (str): The host name of the remote home server we want
- to get the state from.
- event_id (str): The id of the event being requested.
- timeout (int): How long to try (in ms) the destination for before
- giving up. None indicates no timeout.
- Returns:
- Deferred: Results in a dict received from the remote homeserver.
- """
- logger.debug("get_pdu dest=%s, event_id=%s",
- destination, event_id)
- path = PREFIX + "/event/%s/" % (event_id, )
- return self.client.get_json(destination, path=path, timeout=timeout)
- @log_function
- def backfill(self, destination, room_id, event_tuples, limit):
- """ Requests `limit` previous PDUs in a given context before list of
- PDUs.
- Args:
- dest (str)
- room_id (str)
- event_tuples (list)
- limt (int)
- Returns:
- Deferred: Results in a dict received from the remote homeserver.
- """
- logger.debug(
- "backfill dest=%s, room_id=%s, event_tuples=%s, limit=%s",
- destination, room_id, repr(event_tuples), str(limit)
- )
- if not event_tuples:
- # TODO: raise?
- return
- path = PREFIX + "/backfill/%s/" % (room_id,)
- args = {
- "v": event_tuples,
- "limit": [str(limit)],
- }
- return self.client.get_json(
- destination,
- path=path,
- args=args,
- )
- @defer.inlineCallbacks
- @log_function
- def send_transaction(self, transaction, json_data_callback=None):
- """ Sends the given Transaction to its destination
- Args:
- transaction (Transaction)
- Returns:
- Deferred: Results of the deferred is a tuple in the form of
- (response_code, response_body) where the response_body is a
- python dict decoded from json
- """
- logger.debug(
- "send_data dest=%s, txid=%s",
- transaction.destination, transaction.transaction_id
- )
- if transaction.destination == self.server_name:
- raise RuntimeError("Transport layer cannot send to itself!")
- # FIXME: This is only used by the tests. The actual json sent is
- # generated by the json_data_callback.
- json_data = transaction.get_dict()
- response = yield self.client.put_json(
- transaction.destination,
- path=PREFIX + "/send/%s/" % transaction.transaction_id,
- data=json_data,
- json_data_callback=json_data_callback,
- )
- logger.debug(
- "send_data dest=%s, txid=%s, got response: 200",
- transaction.destination, transaction.transaction_id,
- )
- defer.returnValue(response)
- @defer.inlineCallbacks
- @log_function
- def make_query(self, destination, query_type, args, retry_on_dns_fail):
- path = PREFIX + "/query/%s" % query_type
- content = yield self.client.get_json(
- destination=destination,
- path=path,
- args=args,
- retry_on_dns_fail=retry_on_dns_fail,
- )
- defer.returnValue(content)
- @defer.inlineCallbacks
- @log_function
- def make_membership_event(self, destination, room_id, user_id, membership, args={}):
- valid_memberships = {Membership.JOIN, Membership.LEAVE}
- if membership not in valid_memberships:
- raise RuntimeError(
- "make_membership_event called with membership='%s', must be one of %s" %
- (membership, ",".join(valid_memberships))
- )
- path = PREFIX + "/make_%s/%s/%s" % (membership, room_id, user_id)
- content = yield self.client.get_json(
- destination=destination,
- path=path,
- args=args,
- retry_on_dns_fail=True,
- )
- defer.returnValue(content)
- @defer.inlineCallbacks
- @log_function
- def send_join(self, destination, room_id, event_id, content):
- path = PREFIX + "/send_join/%s/%s" % (room_id, event_id)
- response = yield self.client.put_json(
- destination=destination,
- path=path,
- data=content,
- )
- defer.returnValue(response)
- @defer.inlineCallbacks
- @log_function
- def send_leave(self, destination, room_id, event_id, content):
- path = PREFIX + "/send_leave/%s/%s" % (room_id, event_id)
- response = yield self.client.put_json(
- destination=destination,
- path=path,
- data=content,
- )
- defer.returnValue(response)
- @defer.inlineCallbacks
- @log_function
- def send_invite(self, destination, room_id, event_id, content):
- path = PREFIX + "/invite/%s/%s" % (room_id, event_id)
- response = yield self.client.put_json(
- destination=destination,
- path=path,
- data=content,
- )
- defer.returnValue(response)
- @defer.inlineCallbacks
- @log_function
- def get_event_auth(self, destination, room_id, event_id):
- path = PREFIX + "/event_auth/%s/%s" % (room_id, event_id)
- content = yield self.client.get_json(
- destination=destination,
- path=path,
- )
- defer.returnValue(content)
- @defer.inlineCallbacks
- @log_function
- def send_query_auth(self, destination, room_id, event_id, content):
- path = PREFIX + "/query_auth/%s/%s" % (room_id, event_id)
- content = yield self.client.post_json(
- destination=destination,
- path=path,
- data=content,
- )
- defer.returnValue(content)
- @defer.inlineCallbacks
- @log_function
- def query_client_keys(self, destination, query_content):
- """Query the device keys for a list of user ids hosted on a remote
- server.
- Request:
- {
- "device_keys": {
- "<user_id>": ["<device_id>"]
- } }
- Response:
- {
- "device_keys": {
- "<user_id>": {
- "<device_id>": {...}
- } } }
- Args:
- destination(str): The server to query.
- query_content(dict): The user ids to query.
- Returns:
- A dict containg the device keys.
- """
- path = PREFIX + "/user/keys/query"
- content = yield self.client.post_json(
- destination=destination,
- path=path,
- data=query_content,
- )
- defer.returnValue(content)
- @defer.inlineCallbacks
- @log_function
- def claim_client_keys(self, destination, query_content):
- """Claim one-time keys for a list of devices hosted on a remote server.
- Request:
- {
- "one_time_keys": {
- "<user_id>": {
- "<device_id>": "<algorithm>"
- } } }
- Response:
- {
- "device_keys": {
- "<user_id>": {
- "<device_id>": {
- "<algorithm>:<key_id>": "<key_base64>"
- } } } }
- Args:
- destination(str): The server to query.
- query_content(dict): The user ids to query.
- Returns:
- A dict containg the one-time keys.
- """
- path = PREFIX + "/user/keys/claim"
- content = yield self.client.post_json(
- destination=destination,
- path=path,
- data=query_content,
- )
- defer.returnValue(content)
- @defer.inlineCallbacks
- @log_function
- def get_missing_events(self, destination, room_id, earliest_events,
- latest_events, limit, min_depth):
- path = PREFIX + "/get_missing_events/%s" % (room_id,)
- content = yield self.client.post_json(
- destination=destination,
- path=path,
- data={
- "limit": int(limit),
- "min_depth": int(min_depth),
- "earliest_events": earliest_events,
- "latest_events": latest_events,
- }
- )
- defer.returnValue(content)
|