diff --git a/synapse/app/_base.py b/synapse/app/_base.py
index 28062dd69d..f7b866978c 100644
--- a/synapse/app/_base.py
+++ b/synapse/app/_base.py
@@ -41,7 +41,12 @@ from typing_extensions import ParamSpec
import twisted
from twisted.internet import defer, error, reactor as _reactor
-from twisted.internet.interfaces import IOpenSSLContextFactory, IReactorSSL, IReactorTCP
+from twisted.internet.interfaces import (
+ IOpenSSLContextFactory,
+ IReactorSSL,
+ IReactorTCP,
+ IReactorUNIX,
+)
from twisted.internet.protocol import ServerFactory
from twisted.internet.tcp import Port
from twisted.logger import LoggingFile, LogLevel
@@ -56,7 +61,7 @@ from synapse.app.phone_stats_home import start_phone_stats_home
from synapse.config import ConfigError
from synapse.config._base import format_config_error
from synapse.config.homeserver import HomeServerConfig
-from synapse.config.server import ListenerConfig, ManholeConfig
+from synapse.config.server import ListenerConfig, ManholeConfig, TCPListenerConfig
from synapse.crypto import context_factory
from synapse.events.presence_router import load_legacy_presence_router
from synapse.events.spamcheck import load_legacy_spam_checkers
@@ -351,6 +356,28 @@ def listen_tcp(
return r # type: ignore[return-value]
+def listen_unix(
+ path: str,
+ mode: int,
+ factory: ServerFactory,
+ reactor: IReactorUNIX = reactor,
+ backlog: int = 50,
+) -> List[Port]:
+ """
+ Create a UNIX socket for a given path and 'mode' permission
+
+ Returns:
+ list of twisted.internet.tcp.Port listening for TCP connections
+ """
+ wantPID = True
+
+ return [
+ # IReactorUNIX returns an object implementing IListeningPort from listenUNIX,
+ # but we know it will be a Port instance.
+ cast(Port, reactor.listenUNIX(path, factory, backlog, mode, wantPID))
+ ]
+
+
def listen_http(
listener_config: ListenerConfig,
root_resource: Resource,
@@ -359,18 +386,13 @@ def listen_http(
context_factory: Optional[IOpenSSLContextFactory],
reactor: ISynapseReactor = reactor,
) -> List[Port]:
- port = listener_config.port
- bind_addresses = listener_config.bind_addresses
- tls = listener_config.tls
-
assert listener_config.http_options is not None
- site_tag = listener_config.http_options.tag
- if site_tag is None:
- site_tag = str(port)
+ site_tag = listener_config.get_site_tag()
site = SynapseSite(
- "synapse.access.%s.%s" % ("https" if tls else "http", site_tag),
+ "synapse.access.%s.%s"
+ % ("https" if listener_config.is_tls() else "http", site_tag),
site_tag,
listener_config,
root_resource,
@@ -378,25 +400,41 @@ def listen_http(
max_request_body_size=max_request_body_size,
reactor=reactor,
)
- if tls:
- # refresh_certificate should have been called before this.
- assert context_factory is not None
- ports = listen_ssl(
- bind_addresses,
- port,
- site,
- context_factory,
- reactor=reactor,
- )
- logger.info("Synapse now listening on TCP port %d (TLS)", port)
+
+ if isinstance(listener_config, TCPListenerConfig):
+ if listener_config.is_tls():
+ # refresh_certificate should have been called before this.
+ assert context_factory is not None
+ ports = listen_ssl(
+ listener_config.bind_addresses,
+ listener_config.port,
+ site,
+ context_factory,
+ reactor=reactor,
+ )
+ logger.info(
+ "Synapse now listening on TCP port %d (TLS)", listener_config.port
+ )
+ else:
+ ports = listen_tcp(
+ listener_config.bind_addresses,
+ listener_config.port,
+ site,
+ reactor=reactor,
+ )
+ logger.info("Synapse now listening on TCP port %d", listener_config.port)
+
else:
- ports = listen_tcp(
- bind_addresses,
- port,
- site,
- reactor=reactor,
+ ports = listen_unix(
+ listener_config.path, listener_config.mode, site, reactor=reactor
)
- logger.info("Synapse now listening on TCP port %d", port)
+ # getHost() returns a UNIXAddress which contains an instance variable of 'name'
+ # encoded as a byte string. Decode as utf-8 so pretty.
+ logger.info(
+ "Synapse now listening on Unix Socket at: "
+ f"{ports[0].getHost().name.decode('utf-8')}"
+ )
+
return ports
diff --git a/synapse/app/generic_worker.py b/synapse/app/generic_worker.py
index 0dec24369a..e17ce35b8e 100644
--- a/synapse/app/generic_worker.py
+++ b/synapse/app/generic_worker.py
@@ -38,7 +38,7 @@ from synapse.app._base import (
from synapse.config._base import ConfigError
from synapse.config.homeserver import HomeServerConfig
from synapse.config.logger import setup_logging
-from synapse.config.server import ListenerConfig
+from synapse.config.server import ListenerConfig, TCPListenerConfig
from synapse.federation.transport.server import TransportLayerServer
from synapse.http.server import JsonResource, OptionsResource
from synapse.logging.context import LoggingContext
@@ -236,12 +236,18 @@ class GenericWorkerServer(HomeServer):
if listener.type == "http":
self._listen_http(listener)
elif listener.type == "manhole":
- _base.listen_manhole(
- listener.bind_addresses,
- listener.port,
- manhole_settings=self.config.server.manhole_settings,
- manhole_globals={"hs": self},
- )
+ if isinstance(listener, TCPListenerConfig):
+ _base.listen_manhole(
+ listener.bind_addresses,
+ listener.port,
+ manhole_settings=self.config.server.manhole_settings,
+ manhole_globals={"hs": self},
+ )
+ else:
+ raise ConfigError(
+ "Can not using a unix socket for manhole at this time."
+ )
+
elif listener.type == "metrics":
if not self.config.metrics.enable_metrics:
logger.warning(
@@ -249,10 +255,16 @@ class GenericWorkerServer(HomeServer):
"enable_metrics is not True!"
)
else:
- _base.listen_metrics(
- listener.bind_addresses,
- listener.port,
- )
+ if isinstance(listener, TCPListenerConfig):
+ _base.listen_metrics(
+ listener.bind_addresses,
+ listener.port,
+ )
+ else:
+ raise ConfigError(
+ "Can not use a unix socket for metrics at this time."
+ )
+
else:
logger.warning("Unsupported listener type: %s", listener.type)
diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py
index b8830b1a9c..84236ac299 100644
--- a/synapse/app/homeserver.py
+++ b/synapse/app/homeserver.py
@@ -44,7 +44,7 @@ from synapse.app._base import (
)
from synapse.config._base import ConfigError, format_config_error
from synapse.config.homeserver import HomeServerConfig
-from synapse.config.server import ListenerConfig
+from synapse.config.server import ListenerConfig, TCPListenerConfig
from synapse.federation.transport.server import TransportLayerServer
from synapse.http.additional_resource import AdditionalResource
from synapse.http.server import (
@@ -78,14 +78,13 @@ class SynapseHomeServer(HomeServer):
DATASTORE_CLASS = DataStore # type: ignore
def _listener_http(
- self, config: HomeServerConfig, listener_config: ListenerConfig
+ self,
+ config: HomeServerConfig,
+ listener_config: ListenerConfig,
) -> Iterable[Port]:
- port = listener_config.port
# Must exist since this is an HTTP listener.
assert listener_config.http_options is not None
- site_tag = listener_config.http_options.tag
- if site_tag is None:
- site_tag = str(port)
+ site_tag = listener_config.get_site_tag()
# We always include a health resource.
resources: Dict[str, Resource] = {"/health": HealthResource()}
@@ -252,12 +251,17 @@ class SynapseHomeServer(HomeServer):
self._listener_http(self.config, listener)
)
elif listener.type == "manhole":
- _base.listen_manhole(
- listener.bind_addresses,
- listener.port,
- manhole_settings=self.config.server.manhole_settings,
- manhole_globals={"hs": self},
- )
+ if isinstance(listener, TCPListenerConfig):
+ _base.listen_manhole(
+ listener.bind_addresses,
+ listener.port,
+ manhole_settings=self.config.server.manhole_settings,
+ manhole_globals={"hs": self},
+ )
+ else:
+ raise ConfigError(
+ "Can not use a unix socket for manhole at this time."
+ )
elif listener.type == "metrics":
if not self.config.metrics.enable_metrics:
logger.warning(
@@ -265,10 +269,16 @@ class SynapseHomeServer(HomeServer):
"enable_metrics is not True!"
)
else:
- _base.listen_metrics(
- listener.bind_addresses,
- listener.port,
- )
+ if isinstance(listener, TCPListenerConfig):
+ _base.listen_metrics(
+ listener.bind_addresses,
+ listener.port,
+ )
+ else:
+ raise ConfigError(
+ "Can not use a unix socket for metrics at this time."
+ )
+
else:
# this shouldn't happen, as the listener type should have been checked
# during parsing
|