コード例 #1
0
ファイル: devices.py プロジェクト: vishnumg/synapse
    def add_device_change_to_streams(self, user_id, device_ids, hosts):
        """Persist that a user's devices have been updated, and which hosts
        (if any) should be poked.
        """
        if not device_ids:
            return

        with self._device_list_id_gen.get_next_mult(len(device_ids)) as stream_ids:
            yield self.db.runInteraction(
                "add_device_change_to_stream",
                self._add_device_change_to_stream_txn,
                user_id,
                device_ids,
                stream_ids,
            )

        if not hosts:
            return stream_ids[-1]

        context = get_active_span_text_map()
        with self._device_list_id_gen.get_next_mult(
            len(hosts) * len(device_ids)
        ) as stream_ids:
            yield self.db.runInteraction(
                "add_device_outbound_poke_to_stream",
                self._add_device_outbound_poke_to_stream_txn,
                user_id,
                device_ids,
                hosts,
                stream_ids,
                context,
            )

        return stream_ids[-1]
コード例 #2
0
ファイル: devicemessage.py プロジェクト: velas/synapse
    async def send_device_message(
        self,
        sender_user_id: str,
        message_type: str,
        messages: Dict[str, Dict[str, JsonDict]],
    ) -> None:
        set_tag("number_of_messages", len(messages))
        set_tag("sender", sender_user_id)
        local_messages = {}
        remote_messages = {}  # type: Dict[str, Dict[str, Dict[str, JsonDict]]]
        for user_id, by_device in messages.items():
            # we use UserID.from_string to catch invalid user ids
            if self.is_mine(UserID.from_string(user_id)):
                messages_by_device = {
                    device_id: {
                        "content": message_content,
                        "type": message_type,
                        "sender": sender_user_id,
                    }
                    for device_id, message_content in by_device.items()
                }
                if messages_by_device:
                    local_messages[user_id] = messages_by_device
            else:
                destination = get_domain_from_id(user_id)
                remote_messages.setdefault(destination,
                                           {})[user_id] = by_device

        message_id = random_string(16)

        context = get_active_span_text_map()

        remote_edu_contents = {}
        for destination, messages in remote_messages.items():
            with start_active_span("to_device_for_user"):
                set_tag("destination", destination)
                remote_edu_contents[destination] = {
                    "messages": messages,
                    "sender": sender_user_id,
                    "type": message_type,
                    "message_id": message_id,
                    "org.matrix.opentracing_context":
                    json_encoder.encode(context),
                }

        log_kv({"local_messages": local_messages})
        stream_id = await self.store.add_messages_to_device_inbox(
            local_messages, remote_edu_contents)

        self.notifier.on_new_event("to_device_key",
                                   stream_id,
                                   users=local_messages.keys())

        log_kv({"remote_messages": remote_messages})
        if self.federation_sender:
            for destination in remote_messages.keys():
                # Enqueue a new federation transaction to send the new
                # device messages to each remote destination.
                self.federation_sender.send_device_messages(destination)
コード例 #3
0
    def _add_device_change_txn(self, txn, user_id, device_ids, hosts,
                               stream_id):
        now = self._clock.time_msec()

        txn.call_after(self._device_list_stream_cache.entity_has_changed,
                       user_id, stream_id)
        for host in hosts:
            txn.call_after(
                self._device_list_federation_stream_cache.entity_has_changed,
                host,
                stream_id,
            )

        # Delete older entries in the table, as we really only care about
        # when the latest change happened.
        txn.executemany(
            """
            DELETE FROM device_lists_stream
            WHERE user_id = ? AND device_id = ? AND stream_id < ?
            """,
            [(user_id, device_id, stream_id) for device_id in device_ids],
        )

        self._simple_insert_many_txn(
            txn,
            table="device_lists_stream",
            values=[{
                "stream_id": stream_id,
                "user_id": user_id,
                "device_id": device_id
            } for device_id in device_ids],
        )

        context = get_active_span_text_map()

        self._simple_insert_many_txn(
            txn,
            table="device_lists_outbound_pokes",
            values=[{
                "destination":
                destination,
                "stream_id":
                stream_id,
                "user_id":
                user_id,
                "device_id":
                device_id,
                "sent":
                False,
                "ts":
                now,
                "opentracing_context":
                json.dumps(context)
                if whitelisted_homeserver(destination) else "{}",
            } for destination in hosts for device_id in device_ids],
        )
コード例 #4
0
    async def send_device_message(
        self,
        requester: Requester,
        message_type: str,
        messages: Dict[str, Dict[str, JsonDict]],
    ) -> None:
        """
        Handle a request from a user to send to-device message(s).

        Args:
            requester: The user that is sending the to-device messages.
            message_type: The type of to-device messages that are being sent.
            messages: A dictionary containing recipients mapped to messages intended for them.
        """
        sender_user_id = requester.user.to_string()

        message_id = random_string(16)
        set_tag(SynapseTags.TO_DEVICE_MESSAGE_ID, message_id)

        log_kv({"number_of_to_device_messages": len(messages)})
        set_tag("sender", sender_user_id)
        local_messages = {}
        remote_messages: Dict[str, Dict[str, Dict[str, JsonDict]]] = {}
        for user_id, by_device in messages.items():
            # Ratelimit local cross-user key requests by the sending device.
            if (
                message_type == ToDeviceEventTypes.RoomKeyRequest
                and user_id != sender_user_id
            ):
                allowed, _ = await self._ratelimiter.can_do_action(
                    requester, (sender_user_id, requester.device_id)
                )
                if not allowed:
                    logger.info(
                        "Dropping room_key_request from %s to %s due to rate limit",
                        sender_user_id,
                        user_id,
                    )
                    continue

            # we use UserID.from_string to catch invalid user ids
            if self.is_mine(UserID.from_string(user_id)):
                messages_by_device = {
                    device_id: {
                        "content": message_content,
                        "type": message_type,
                        "sender": sender_user_id,
                        "message_id": message_id,
                    }
                    for device_id, message_content in by_device.items()
                }
                if messages_by_device:
                    local_messages[user_id] = messages_by_device
                    log_kv(
                        {
                            "user_id": user_id,
                            "device_id": list(messages_by_device),
                        }
                    )
            else:
                destination = get_domain_from_id(user_id)
                remote_messages.setdefault(destination, {})[user_id] = by_device

        context = get_active_span_text_map()

        remote_edu_contents = {}
        for destination, messages in remote_messages.items():
            log_kv({"destination": destination})
            remote_edu_contents[destination] = {
                "messages": messages,
                "sender": sender_user_id,
                "type": message_type,
                "message_id": message_id,
                "org.matrix.opentracing_context": json_encoder.encode(context),
            }

        # Add messages to the database.
        # Retrieve the stream id of the last-processed to-device message.
        last_stream_id = await self.store.add_messages_to_device_inbox(
            local_messages, remote_edu_contents
        )

        # Notify listeners that there are new to-device messages to process,
        # handing them the latest stream id.
        self.notifier.on_new_event(
            "to_device_key", last_stream_id, users=local_messages.keys()
        )

        if self.federation_sender:
            for destination in remote_messages.keys():
                # Enqueue a new federation transaction to send the new
                # device messages to each remote destination.
                self.federation_sender.send_device_messages(destination)
コード例 #5
0
    async def send_device_message(
        self,
        requester: Requester,
        message_type: str,
        messages: Dict[str, Dict[str, JsonDict]],
    ) -> None:
        sender_user_id = requester.user.to_string()

        message_id = random_string(16)
        set_tag(SynapseTags.TO_DEVICE_MESSAGE_ID, message_id)

        log_kv({"number_of_to_device_messages": len(messages)})
        set_tag("sender", sender_user_id)
        local_messages = {}
        remote_messages = {}  # type: Dict[str, Dict[str, Dict[str, JsonDict]]]
        for user_id, by_device in messages.items():
            # Ratelimit local cross-user key requests by the sending device.
            if (message_type == EduTypes.RoomKeyRequest
                    and user_id != sender_user_id
                    and await self._ratelimiter.can_do_action(
                        requester, (sender_user_id, requester.device_id))):
                continue

            # we use UserID.from_string to catch invalid user ids
            if self.is_mine(UserID.from_string(user_id)):
                messages_by_device = {
                    device_id: {
                        "content": message_content,
                        "type": message_type,
                        "sender": sender_user_id,
                        "message_id": message_id,
                    }
                    for device_id, message_content in by_device.items()
                }
                if messages_by_device:
                    local_messages[user_id] = messages_by_device
                    log_kv({
                        "user_id": user_id,
                        "device_id": list(messages_by_device),
                    })
            else:
                destination = get_domain_from_id(user_id)
                remote_messages.setdefault(destination,
                                           {})[user_id] = by_device

        context = get_active_span_text_map()

        remote_edu_contents = {}
        for destination, messages in remote_messages.items():
            log_kv({"destination": destination})
            remote_edu_contents[destination] = {
                "messages": messages,
                "sender": sender_user_id,
                "type": message_type,
                "message_id": message_id,
                "org.matrix.opentracing_context": json_encoder.encode(context),
            }

        stream_id = await self.store.add_messages_to_device_inbox(
            local_messages, remote_edu_contents)

        self.notifier.on_new_event("to_device_key",
                                   stream_id,
                                   users=local_messages.keys())

        if self.federation_sender:
            for destination in remote_messages.keys():
                # Enqueue a new federation transaction to send the new
                # device messages to each remote destination.
                self.federation_sender.send_device_messages(destination)