1# Copyright 2021 The Matrix.org Foundation C.I.C.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15
16# This file provides some classes for setting up (partially-populated)
17# homeservers; either as a full homeserver as a real application, or a small
18# partial one for unit test mocking.
19
20# Imports required for the default HomeServer() implementation
21import abc
22import functools
23import logging
24from typing import (
25    TYPE_CHECKING,
26    Any,
27    Callable,
28    Dict,
29    List,
30    Optional,
31    TypeVar,
32    Union,
33    cast,
34)
35
36from twisted.internet.interfaces import IOpenSSLContextFactory
37from twisted.internet.tcp import Port
38from twisted.web.iweb import IPolicyForHTTPS
39from twisted.web.resource import Resource
40
41from synapse.api.auth import Auth
42from synapse.api.filtering import Filtering
43from synapse.api.ratelimiting import Ratelimiter, RequestRatelimiter
44from synapse.appservice.api import ApplicationServiceApi
45from synapse.appservice.scheduler import ApplicationServiceScheduler
46from synapse.config.homeserver import HomeServerConfig
47from synapse.crypto import context_factory
48from synapse.crypto.context_factory import RegularPolicyForHTTPS
49from synapse.crypto.keyring import Keyring
50from synapse.events.builder import EventBuilderFactory
51from synapse.events.presence_router import PresenceRouter
52from synapse.events.spamcheck import SpamChecker
53from synapse.events.third_party_rules import ThirdPartyEventRules
54from synapse.events.utils import EventClientSerializer
55from synapse.federation.federation_client import FederationClient
56from synapse.federation.federation_server import (
57    FederationHandlerRegistry,
58    FederationServer,
59)
60from synapse.federation.send_queue import FederationRemoteSendQueue
61from synapse.federation.sender import AbstractFederationSender, FederationSender
62from synapse.federation.transport.client import TransportLayerClient
63from synapse.groups.attestations import GroupAttestationSigning, GroupAttestionRenewer
64from synapse.groups.groups_server import GroupsServerHandler, GroupsServerWorkerHandler
65from synapse.handlers.account_data import AccountDataHandler
66from synapse.handlers.account_validity import AccountValidityHandler
67from synapse.handlers.admin import AdminHandler
68from synapse.handlers.appservice import ApplicationServicesHandler
69from synapse.handlers.auth import AuthHandler, MacaroonGenerator, PasswordAuthProvider
70from synapse.handlers.cas import CasHandler
71from synapse.handlers.deactivate_account import DeactivateAccountHandler
72from synapse.handlers.device import DeviceHandler, DeviceWorkerHandler
73from synapse.handlers.devicemessage import DeviceMessageHandler
74from synapse.handlers.directory import DirectoryHandler
75from synapse.handlers.e2e_keys import E2eKeysHandler
76from synapse.handlers.e2e_room_keys import E2eRoomKeysHandler
77from synapse.handlers.event_auth import EventAuthHandler
78from synapse.handlers.events import EventHandler, EventStreamHandler
79from synapse.handlers.federation import FederationHandler
80from synapse.handlers.federation_event import FederationEventHandler
81from synapse.handlers.groups_local import GroupsLocalHandler, GroupsLocalWorkerHandler
82from synapse.handlers.identity import IdentityHandler
83from synapse.handlers.initial_sync import InitialSyncHandler
84from synapse.handlers.message import EventCreationHandler, MessageHandler
85from synapse.handlers.pagination import PaginationHandler
86from synapse.handlers.password_policy import PasswordPolicyHandler
87from synapse.handlers.presence import (
88    BasePresenceHandler,
89    PresenceHandler,
90    WorkerPresenceHandler,
91)
92from synapse.handlers.profile import ProfileHandler
93from synapse.handlers.read_marker import ReadMarkerHandler
94from synapse.handlers.receipts import ReceiptsHandler
95from synapse.handlers.register import RegistrationHandler
96from synapse.handlers.room import (
97    RoomContextHandler,
98    RoomCreationHandler,
99    RoomShutdownHandler,
100    TimestampLookupHandler,
101)
102from synapse.handlers.room_batch import RoomBatchHandler
103from synapse.handlers.room_list import RoomListHandler
104from synapse.handlers.room_member import RoomMemberHandler, RoomMemberMasterHandler
105from synapse.handlers.room_member_worker import RoomMemberWorkerHandler
106from synapse.handlers.room_summary import RoomSummaryHandler
107from synapse.handlers.search import SearchHandler
108from synapse.handlers.send_email import SendEmailHandler
109from synapse.handlers.set_password import SetPasswordHandler
110from synapse.handlers.sso import SsoHandler
111from synapse.handlers.stats import StatsHandler
112from synapse.handlers.sync import SyncHandler
113from synapse.handlers.typing import FollowerTypingHandler, TypingWriterHandler
114from synapse.handlers.user_directory import UserDirectoryHandler
115from synapse.http.client import InsecureInterceptableContextFactory, SimpleHttpClient
116from synapse.http.matrixfederationclient import MatrixFederationHttpClient
117from synapse.module_api import ModuleApi
118from synapse.notifier import Notifier
119from synapse.push.action_generator import ActionGenerator
120from synapse.push.pusherpool import PusherPool
121from synapse.replication.tcp.client import ReplicationDataHandler
122from synapse.replication.tcp.external_cache import ExternalCache
123from synapse.replication.tcp.handler import ReplicationCommandHandler
124from synapse.replication.tcp.resource import ReplicationStreamer
125from synapse.replication.tcp.streams import STREAMS_MAP, Stream
126from synapse.rest.media.v1.media_repository import (
127    MediaRepository,
128    MediaRepositoryResource,
129)
130from synapse.server_notices.server_notices_manager import ServerNoticesManager
131from synapse.server_notices.server_notices_sender import ServerNoticesSender
132from synapse.server_notices.worker_server_notices_sender import (
133    WorkerServerNoticesSender,
134)
135from synapse.state import StateHandler, StateResolutionHandler
136from synapse.storage import Databases, DataStore, Storage
137from synapse.streams.events import EventSources
138from synapse.types import DomainSpecificString, ISynapseReactor
139from synapse.util import Clock
140from synapse.util.distributor import Distributor
141from synapse.util.ratelimitutils import FederationRateLimiter
142from synapse.util.stringutils import random_string
143
144logger = logging.getLogger(__name__)
145
146if TYPE_CHECKING:
147    from txredisapi import RedisProtocol
148
149    from synapse.handlers.oidc import OidcHandler
150    from synapse.handlers.saml import SamlHandler
151
152
153T = TypeVar("T", bound=Callable[..., Any])
154
155
156def cache_in_self(builder: T) -> T:
157    """Wraps a function called e.g. `get_foo`, checking if `self.foo` exists and
158    returning if so. If not, calls the given function and sets `self.foo` to it.
159
160    Also ensures that dependency cycles throw an exception correctly, rather
161    than overflowing the stack.
162    """
163
164    if not builder.__name__.startswith("get_"):
165        raise Exception(
166            "@cache_in_self can only be used on functions starting with `get_`"
167        )
168
169    # get_attr -> _attr
170    depname = builder.__name__[len("get") :]
171
172    building = [False]
173
174    @functools.wraps(builder)
175    def _get(self):
176        try:
177            return getattr(self, depname)
178        except AttributeError:
179            pass
180
181        # Prevent cyclic dependencies from deadlocking
182        if building[0]:
183            raise ValueError("Cyclic dependency while building %s" % (depname,))
184
185        building[0] = True
186        try:
187            dep = builder(self)
188            setattr(self, depname, dep)
189        finally:
190            building[0] = False
191
192        return dep
193
194    # We cast here as we need to tell mypy that `_get` has the same signature as
195    # `builder`.
196    return cast(T, _get)
197
198
199class HomeServer(metaclass=abc.ABCMeta):
200    """A basic homeserver object without lazy component builders.
201
202    This will need all of the components it requires to either be passed as
203    constructor arguments, or the relevant methods overriding to create them.
204    Typically this would only be used for unit tests.
205
206    Dependencies should be added by creating a `def get_<depname>(self)`
207    function, wrapping it in `@cache_in_self`.
208
209    Attributes:
210        config (synapse.config.homeserver.HomeserverConfig):
211        _listening_services (list[Port]): TCP ports that
212            we are listening on to provide HTTP services.
213    """
214
215    REQUIRED_ON_BACKGROUND_TASK_STARTUP = [
216        "account_validity",
217        "auth",
218        "deactivate_account",
219        "message",
220        "pagination",
221        "profile",
222        "stats",
223    ]
224
225    # This is overridden in derived application classes
226    # (such as synapse.app.homeserver.SynapseHomeServer) and gives the class to be
227    # instantiated during setup() for future return by get_datastore()
228    DATASTORE_CLASS = abc.abstractproperty()
229
230    tls_server_context_factory: Optional[IOpenSSLContextFactory]
231
232    def __init__(
233        self,
234        hostname: str,
235        config: HomeServerConfig,
236        reactor=None,
237        version_string="Synapse",
238    ):
239        """
240        Args:
241            hostname : The hostname for the server.
242            config: The full config for the homeserver.
243        """
244        if not reactor:
245            from twisted.internet import reactor as _reactor
246
247            reactor = _reactor
248
249        self._reactor = reactor
250        self.hostname = hostname
251        # the key we use to sign events and requests
252        self.signing_key = config.key.signing_key[0]
253        self.config = config
254        self._listening_services: List[Port] = []
255        self.start_time: Optional[int] = None
256
257        self._instance_id = random_string(5)
258        self._instance_name = config.worker.instance_name
259
260        self.version_string = version_string
261
262        self.datastores: Optional[Databases] = None
263
264        self._module_web_resources: Dict[str, Resource] = {}
265        self._module_web_resources_consumed = False
266
267    def register_module_web_resource(self, path: str, resource: Resource):
268        """Allows a module to register a web resource to be served at the given path.
269
270        If multiple modules register a resource for the same path, the module that
271        appears the highest in the configuration file takes priority.
272
273        Args:
274            path: The path to register the resource for.
275            resource: The resource to attach to this path.
276
277        Raises:
278            SynapseError(500): A module tried to register a web resource after the HTTP
279                listeners have been started.
280        """
281        if self._module_web_resources_consumed:
282            raise RuntimeError(
283                "Tried to register a web resource from a module after startup",
284            )
285
286        # Don't register a resource that's already been registered.
287        if path not in self._module_web_resources.keys():
288            self._module_web_resources[path] = resource
289        else:
290            logger.warning(
291                "Module tried to register a web resource for path %s but another module"
292                " has already registered a resource for this path.",
293                path,
294            )
295
296    def get_instance_id(self) -> str:
297        """A unique ID for this synapse process instance.
298
299        This is used to distinguish running instances in worker-based
300        deployments.
301        """
302        return self._instance_id
303
304    def get_instance_name(self) -> str:
305        """A unique name for this synapse process.
306
307        Used to identify the process over replication and in config. Does not
308        change over restarts.
309        """
310        return self._instance_name
311
312    def setup(self) -> None:
313        logger.info("Setting up.")
314        self.start_time = int(self.get_clock().time())
315        self.datastores = Databases(self.DATASTORE_CLASS, self)
316        logger.info("Finished setting up.")
317
318        # Register background tasks required by this server. This must be done
319        # somewhat manually due to the background tasks not being registered
320        # unless handlers are instantiated.
321        if self.config.worker.run_background_tasks:
322            self.setup_background_tasks()
323
324    def start_listening(self) -> None:
325        """Start the HTTP, manhole, metrics, etc listeners
326
327        Does nothing in this base class; overridden in derived classes to start the
328        appropriate listeners.
329        """
330        pass
331
332    def setup_background_tasks(self) -> None:
333        """
334        Some handlers have side effects on instantiation (like registering
335        background updates). This function causes them to be fetched, and
336        therefore instantiated, to run those side effects.
337        """
338        for i in self.REQUIRED_ON_BACKGROUND_TASK_STARTUP:
339            getattr(self, "get_" + i + "_handler")()
340
341    def get_reactor(self) -> ISynapseReactor:
342        """
343        Fetch the Twisted reactor in use by this HomeServer.
344        """
345        return self._reactor
346
347    def is_mine(self, domain_specific_string: DomainSpecificString) -> bool:
348        return domain_specific_string.domain == self.hostname
349
350    def is_mine_id(self, string: str) -> bool:
351        return string.split(":", 1)[1] == self.hostname
352
353    @cache_in_self
354    def get_clock(self) -> Clock:
355        return Clock(self._reactor)
356
357    def get_datastore(self) -> DataStore:
358        if not self.datastores:
359            raise Exception("HomeServer.setup must be called before getting datastores")
360
361        return self.datastores.main
362
363    def get_datastores(self) -> Databases:
364        if not self.datastores:
365            raise Exception("HomeServer.setup must be called before getting datastores")
366
367        return self.datastores
368
369    @cache_in_self
370    def get_distributor(self) -> Distributor:
371        return Distributor()
372
373    @cache_in_self
374    def get_registration_ratelimiter(self) -> Ratelimiter:
375        return Ratelimiter(
376            store=self.get_datastore(),
377            clock=self.get_clock(),
378            rate_hz=self.config.ratelimiting.rc_registration.per_second,
379            burst_count=self.config.ratelimiting.rc_registration.burst_count,
380        )
381
382    @cache_in_self
383    def get_federation_client(self) -> FederationClient:
384        return FederationClient(self)
385
386    @cache_in_self
387    def get_federation_server(self) -> FederationServer:
388        return FederationServer(self)
389
390    @cache_in_self
391    def get_notifier(self) -> Notifier:
392        return Notifier(self)
393
394    @cache_in_self
395    def get_auth(self) -> Auth:
396        return Auth(self)
397
398    @cache_in_self
399    def get_http_client_context_factory(self) -> IPolicyForHTTPS:
400        if self.config.tls.use_insecure_ssl_client_just_for_testing_do_not_use:
401            return InsecureInterceptableContextFactory()
402        return RegularPolicyForHTTPS()
403
404    @cache_in_self
405    def get_simple_http_client(self) -> SimpleHttpClient:
406        """
407        An HTTP client with no special configuration.
408        """
409        return SimpleHttpClient(self)
410
411    @cache_in_self
412    def get_proxied_http_client(self) -> SimpleHttpClient:
413        """
414        An HTTP client that uses configured HTTP(S) proxies.
415        """
416        return SimpleHttpClient(self, use_proxy=True)
417
418    @cache_in_self
419    def get_proxied_blacklisted_http_client(self) -> SimpleHttpClient:
420        """
421        An HTTP client that uses configured HTTP(S) proxies and blacklists IPs
422        based on the IP range blacklist/whitelist.
423        """
424        return SimpleHttpClient(
425            self,
426            ip_whitelist=self.config.server.ip_range_whitelist,
427            ip_blacklist=self.config.server.ip_range_blacklist,
428            use_proxy=True,
429        )
430
431    @cache_in_self
432    def get_federation_http_client(self) -> MatrixFederationHttpClient:
433        """
434        An HTTP client for federation.
435        """
436        tls_client_options_factory = context_factory.FederationPolicyForHTTPS(
437            self.config
438        )
439        return MatrixFederationHttpClient(self, tls_client_options_factory)
440
441    @cache_in_self
442    def get_room_creation_handler(self) -> RoomCreationHandler:
443        return RoomCreationHandler(self)
444
445    @cache_in_self
446    def get_room_batch_handler(self) -> RoomBatchHandler:
447        return RoomBatchHandler(self)
448
449    @cache_in_self
450    def get_room_shutdown_handler(self) -> RoomShutdownHandler:
451        return RoomShutdownHandler(self)
452
453    @cache_in_self
454    def get_state_handler(self) -> StateHandler:
455        return StateHandler(self)
456
457    @cache_in_self
458    def get_state_resolution_handler(self) -> StateResolutionHandler:
459        return StateResolutionHandler(self)
460
461    @cache_in_self
462    def get_presence_handler(self) -> BasePresenceHandler:
463        if self.get_instance_name() in self.config.worker.writers.presence:
464            return PresenceHandler(self)
465        else:
466            return WorkerPresenceHandler(self)
467
468    @cache_in_self
469    def get_typing_writer_handler(self) -> TypingWriterHandler:
470        if self.get_instance_name() in self.config.worker.writers.typing:
471            return TypingWriterHandler(self)
472        else:
473            raise Exception("Workers cannot write typing")
474
475    @cache_in_self
476    def get_presence_router(self) -> PresenceRouter:
477        return PresenceRouter(self)
478
479    @cache_in_self
480    def get_typing_handler(self) -> FollowerTypingHandler:
481        if self.get_instance_name() in self.config.worker.writers.typing:
482            # Use get_typing_writer_handler to ensure that we use the same
483            # cached version.
484            return self.get_typing_writer_handler()
485        else:
486            return FollowerTypingHandler(self)
487
488    @cache_in_self
489    def get_sso_handler(self) -> SsoHandler:
490        return SsoHandler(self)
491
492    @cache_in_self
493    def get_sync_handler(self) -> SyncHandler:
494        return SyncHandler(self)
495
496    @cache_in_self
497    def get_room_list_handler(self) -> RoomListHandler:
498        return RoomListHandler(self)
499
500    @cache_in_self
501    def get_auth_handler(self) -> AuthHandler:
502        return AuthHandler(self)
503
504    @cache_in_self
505    def get_macaroon_generator(self) -> MacaroonGenerator:
506        return MacaroonGenerator(self)
507
508    @cache_in_self
509    def get_device_handler(self):
510        if self.config.worker.worker_app:
511            return DeviceWorkerHandler(self)
512        else:
513            return DeviceHandler(self)
514
515    @cache_in_self
516    def get_device_message_handler(self) -> DeviceMessageHandler:
517        return DeviceMessageHandler(self)
518
519    @cache_in_self
520    def get_directory_handler(self) -> DirectoryHandler:
521        return DirectoryHandler(self)
522
523    @cache_in_self
524    def get_e2e_keys_handler(self) -> E2eKeysHandler:
525        return E2eKeysHandler(self)
526
527    @cache_in_self
528    def get_e2e_room_keys_handler(self) -> E2eRoomKeysHandler:
529        return E2eRoomKeysHandler(self)
530
531    @cache_in_self
532    def get_admin_handler(self) -> AdminHandler:
533        return AdminHandler(self)
534
535    @cache_in_self
536    def get_application_service_api(self) -> ApplicationServiceApi:
537        return ApplicationServiceApi(self)
538
539    @cache_in_self
540    def get_application_service_scheduler(self) -> ApplicationServiceScheduler:
541        return ApplicationServiceScheduler(self)
542
543    @cache_in_self
544    def get_application_service_handler(self) -> ApplicationServicesHandler:
545        return ApplicationServicesHandler(self)
546
547    @cache_in_self
548    def get_event_handler(self) -> EventHandler:
549        return EventHandler(self)
550
551    @cache_in_self
552    def get_event_stream_handler(self) -> EventStreamHandler:
553        return EventStreamHandler(self)
554
555    @cache_in_self
556    def get_federation_handler(self) -> FederationHandler:
557        return FederationHandler(self)
558
559    @cache_in_self
560    def get_federation_event_handler(self) -> FederationEventHandler:
561        return FederationEventHandler(self)
562
563    @cache_in_self
564    def get_identity_handler(self) -> IdentityHandler:
565        return IdentityHandler(self)
566
567    @cache_in_self
568    def get_initial_sync_handler(self) -> InitialSyncHandler:
569        return InitialSyncHandler(self)
570
571    @cache_in_self
572    def get_profile_handler(self) -> ProfileHandler:
573        return ProfileHandler(self)
574
575    @cache_in_self
576    def get_event_creation_handler(self) -> EventCreationHandler:
577        return EventCreationHandler(self)
578
579    @cache_in_self
580    def get_deactivate_account_handler(self) -> DeactivateAccountHandler:
581        return DeactivateAccountHandler(self)
582
583    @cache_in_self
584    def get_search_handler(self) -> SearchHandler:
585        return SearchHandler(self)
586
587    @cache_in_self
588    def get_send_email_handler(self) -> SendEmailHandler:
589        return SendEmailHandler(self)
590
591    @cache_in_self
592    def get_set_password_handler(self) -> SetPasswordHandler:
593        return SetPasswordHandler(self)
594
595    @cache_in_self
596    def get_event_sources(self) -> EventSources:
597        return EventSources(self)
598
599    @cache_in_self
600    def get_keyring(self) -> Keyring:
601        return Keyring(self)
602
603    @cache_in_self
604    def get_event_builder_factory(self) -> EventBuilderFactory:
605        return EventBuilderFactory(self)
606
607    @cache_in_self
608    def get_filtering(self) -> Filtering:
609        return Filtering(self)
610
611    @cache_in_self
612    def get_pusherpool(self) -> PusherPool:
613        return PusherPool(self)
614
615    @cache_in_self
616    def get_media_repository_resource(self) -> MediaRepositoryResource:
617        # build the media repo resource. This indirects through the HomeServer
618        # to ensure that we only have a single instance of
619        return MediaRepositoryResource(self)
620
621    @cache_in_self
622    def get_media_repository(self) -> MediaRepository:
623        return MediaRepository(self)
624
625    @cache_in_self
626    def get_federation_transport_client(self) -> TransportLayerClient:
627        return TransportLayerClient(self)
628
629    @cache_in_self
630    def get_federation_sender(self) -> AbstractFederationSender:
631        if self.should_send_federation():
632            return FederationSender(self)
633        elif not self.config.worker.worker_app:
634            return FederationRemoteSendQueue(self)
635        else:
636            raise Exception("Workers cannot send federation traffic")
637
638    @cache_in_self
639    def get_receipts_handler(self) -> ReceiptsHandler:
640        return ReceiptsHandler(self)
641
642    @cache_in_self
643    def get_read_marker_handler(self) -> ReadMarkerHandler:
644        return ReadMarkerHandler(self)
645
646    @cache_in_self
647    def get_tcp_replication(self) -> ReplicationCommandHandler:
648        return ReplicationCommandHandler(self)
649
650    @cache_in_self
651    def get_action_generator(self) -> ActionGenerator:
652        return ActionGenerator(self)
653
654    @cache_in_self
655    def get_user_directory_handler(self) -> UserDirectoryHandler:
656        return UserDirectoryHandler(self)
657
658    @cache_in_self
659    def get_groups_local_handler(
660        self,
661    ) -> Union[GroupsLocalWorkerHandler, GroupsLocalHandler]:
662        if self.config.worker.worker_app:
663            return GroupsLocalWorkerHandler(self)
664        else:
665            return GroupsLocalHandler(self)
666
667    @cache_in_self
668    def get_groups_server_handler(self):
669        if self.config.worker.worker_app:
670            return GroupsServerWorkerHandler(self)
671        else:
672            return GroupsServerHandler(self)
673
674    @cache_in_self
675    def get_groups_attestation_signing(self) -> GroupAttestationSigning:
676        return GroupAttestationSigning(self)
677
678    @cache_in_self
679    def get_groups_attestation_renewer(self) -> GroupAttestionRenewer:
680        return GroupAttestionRenewer(self)
681
682    @cache_in_self
683    def get_stats_handler(self) -> StatsHandler:
684        return StatsHandler(self)
685
686    @cache_in_self
687    def get_spam_checker(self) -> SpamChecker:
688        return SpamChecker()
689
690    @cache_in_self
691    def get_third_party_event_rules(self) -> ThirdPartyEventRules:
692        return ThirdPartyEventRules(self)
693
694    @cache_in_self
695    def get_password_auth_provider(self) -> PasswordAuthProvider:
696        return PasswordAuthProvider()
697
698    @cache_in_self
699    def get_room_member_handler(self) -> RoomMemberHandler:
700        if self.config.worker.worker_app:
701            return RoomMemberWorkerHandler(self)
702        return RoomMemberMasterHandler(self)
703
704    @cache_in_self
705    def get_federation_registry(self) -> FederationHandlerRegistry:
706        return FederationHandlerRegistry(self)
707
708    @cache_in_self
709    def get_server_notices_manager(self) -> ServerNoticesManager:
710        if self.config.worker.worker_app:
711            raise Exception("Workers cannot send server notices")
712        return ServerNoticesManager(self)
713
714    @cache_in_self
715    def get_server_notices_sender(self) -> WorkerServerNoticesSender:
716        if self.config.worker.worker_app:
717            return WorkerServerNoticesSender(self)
718        return ServerNoticesSender(self)
719
720    @cache_in_self
721    def get_message_handler(self) -> MessageHandler:
722        return MessageHandler(self)
723
724    @cache_in_self
725    def get_pagination_handler(self) -> PaginationHandler:
726        return PaginationHandler(self)
727
728    @cache_in_self
729    def get_room_context_handler(self) -> RoomContextHandler:
730        return RoomContextHandler(self)
731
732    @cache_in_self
733    def get_timestamp_lookup_handler(self) -> TimestampLookupHandler:
734        return TimestampLookupHandler(self)
735
736    @cache_in_self
737    def get_registration_handler(self) -> RegistrationHandler:
738        return RegistrationHandler(self)
739
740    @cache_in_self
741    def get_account_validity_handler(self) -> AccountValidityHandler:
742        return AccountValidityHandler(self)
743
744    @cache_in_self
745    def get_cas_handler(self) -> CasHandler:
746        return CasHandler(self)
747
748    @cache_in_self
749    def get_saml_handler(self) -> "SamlHandler":
750        from synapse.handlers.saml import SamlHandler
751
752        return SamlHandler(self)
753
754    @cache_in_self
755    def get_oidc_handler(self) -> "OidcHandler":
756        from synapse.handlers.oidc import OidcHandler
757
758        return OidcHandler(self)
759
760    @cache_in_self
761    def get_event_client_serializer(self) -> EventClientSerializer:
762        return EventClientSerializer(self)
763
764    @cache_in_self
765    def get_password_policy_handler(self) -> PasswordPolicyHandler:
766        return PasswordPolicyHandler(self)
767
768    @cache_in_self
769    def get_storage(self) -> Storage:
770        return Storage(self, self.get_datastores())
771
772    @cache_in_self
773    def get_replication_streamer(self) -> ReplicationStreamer:
774        return ReplicationStreamer(self)
775
776    @cache_in_self
777    def get_replication_data_handler(self) -> ReplicationDataHandler:
778        return ReplicationDataHandler(self)
779
780    @cache_in_self
781    def get_replication_streams(self) -> Dict[str, Stream]:
782        return {stream.NAME: stream(self) for stream in STREAMS_MAP.values()}
783
784    @cache_in_self
785    def get_federation_ratelimiter(self) -> FederationRateLimiter:
786        return FederationRateLimiter(
787            self.get_clock(), config=self.config.ratelimiting.rc_federation
788        )
789
790    @cache_in_self
791    def get_module_api(self) -> ModuleApi:
792        return ModuleApi(self, self.get_auth_handler())
793
794    @cache_in_self
795    def get_account_data_handler(self) -> AccountDataHandler:
796        return AccountDataHandler(self)
797
798    @cache_in_self
799    def get_room_summary_handler(self) -> RoomSummaryHandler:
800        return RoomSummaryHandler(self)
801
802    @cache_in_self
803    def get_event_auth_handler(self) -> EventAuthHandler:
804        return EventAuthHandler(self)
805
806    @cache_in_self
807    def get_external_cache(self) -> ExternalCache:
808        return ExternalCache(self)
809
810    @cache_in_self
811    def get_outbound_redis_connection(self) -> "RedisProtocol":
812        """
813        The Redis connection used for replication.
814
815        Raises:
816            AssertionError: if Redis is not enabled in the homeserver config.
817        """
818        assert self.config.redis.redis_enabled
819
820        # We only want to import redis module if we're using it, as we have
821        # `txredisapi` as an optional dependency.
822        from synapse.replication.tcp.redis import lazyConnection
823
824        logger.info(
825            "Connecting to redis (host=%r port=%r) for external cache",
826            self.config.redis.redis_host,
827            self.config.redis.redis_port,
828        )
829
830        return lazyConnection(
831            hs=self,
832            host=self.config.redis.redis_host,
833            port=self.config.redis.redis_port,
834            password=self.config.redis.redis_password,
835            reconnect=True,
836        )
837
838    def should_send_federation(self) -> bool:
839        "Should this server be sending federation traffic directly?"
840        return self.config.worker.send_federation
841
842    @cache_in_self
843    def get_request_ratelimiter(self) -> RequestRatelimiter:
844        return RequestRatelimiter(
845            self.get_datastore(),
846            self.get_clock(),
847            self.config.ratelimiting.rc_message,
848            self.config.ratelimiting.rc_admin_redaction,
849        )
850