Files
synapse/rust/Cargo.toml
T
Erik JohnstonandClaude Opus 5.5 6a2ac9be0e Add a Rust federation agent
The Rust replacement for `MatrixFederationAgent` and its connection pool,
as a library: nothing in Synapse sends through it yet. The request layer
(signing, retries, backoff) comes next and will be its first caller.

`Agent::request` takes a `matrix-federation://` request, applies
`.well-known` delegation to the URI and the `Host` header, and sends it
through hyper-util's pooled client (5 idle connections per host, 120s
idle timeout, HTTP/1.1, no automatic retries), as Python's pool does.

The pool calls our connector, derived from matrix-hyper-federation-
client's `MatrixConnector` (Apache-2.0). It resolves the server name
(SRV), tries each server in order and returns the first error if all
fail. For each server it resolves addresses through the IP range policy,
connects TCP with Twisted's staggered attempts and 30s timeout, or
tunnels through `https_proxy` with `CONNECT` unless `no_proxy` exempts
the host, then does TLS verified against the delegated server name,
never the SRV target. The `.well-known` fetch shares the pool and, as in
Python, blocks IP literals by the blocklist alone.

Failures are a typed `TransportError` (DNS, connect, TLS, and so on), so
the request layer can tell a DNS failure from the rest. The agent
implements `FederationTransport`.

`RustFederationAgentForTest` exposes a blocking `request` to Python. The
trial tests drive it against a real TLS server on a thread, signed by
the test CA, covering the delegation, SRV, SNI, IP literal, blocklist,
certificate verification and connection reuse cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5b7Ruy4cgt27Mjq6Ptxbb
2026-10-15 14:54:15 +00:00

146 lines
4.5 KiB
TOML

[package]
# We name the package `synapse` so that things like logging have the right
# logging target.
name = "synapse"
# dummy version. See pyproject.toml for the Synapse's version number.
version = "0.1.0"
edition = "2021"
rust-version = "1.82.0"
[lib]
name = "synapse"
# We generate a `cdylib` for Python and a standard `lib` for running
# tests/benchmarks.
crate-type = ["lib", "cdylib"]
# This is deprecated, see tool.maturin in pyproject.toml.
# It is left here for compatibilty with maturin < 0.15.
[package.metadata.maturin]
# This is where we tell maturin where to place the built library.
name = "synapse.synapse_rust"
[dependencies]
async-trait = "0.1.89"
anyhow = "1.0.63"
base64 = "0.23.1"
bytes = "1.6.0"
# Matches the version postgres-protocol uses, for iterating a decoded array's
# elements (`ArrayValues` is a `FallibleIterator`); see database/postgres/value.rs.
fallible-iterator = "0.2"
headers = "0.4.0"
http = "1.1.0"
lazy_static = "1.4.0"
libc = "0.2.174"
log = "0.4.17"
mime = "0.3.17"
pyo3 = { version = "0.29.0", features = [
"macros",
"anyhow",
"abi3",
"abi3-py310",
# So we can pass `bytes::Bytes` directly back to Python efficiently,
# https://docs.rs/pyo3/latest/pyo3/bytes/index.html
"bytes",
] }
pyo3-log = "0.13.4"
pythonize = { version = "0.29.0", features = ["arbitrary_precision"] }
regex = "1.6.0"
sha2 = "0.11.0"
serde = { version = "1.0.144", features = ["derive", "rc"] }
serde_json = { version = "1.0.85", features = [
"raw_value",
# We need to be able to parse arbitrary precision numbers, as some numbers
# in the database may be out of range of i64 (as Python uses arbitrary
# precision integers).
"arbitrary_precision",
] }
ulid = "3.0.0"
icu_segmenter = "2.0.0"
reqwest = { version = "0.12.15", default-features = false, features = [
"http2",
"stream",
"rustls-tls-native-roots",
] }
http-body-util = "0.1.3"
futures = "0.3.31"
tokio = { version = "1.44.2", features = [
"rt",
"rt-multi-thread",
"net",
"time",
"sync",
"io-util",
] }
tokio-postgres = "0.7"
# Connection pooling for the native Rust Postgres backend. We use the generic
# `deadpool::managed` pool with our own manager (rather than `deadpool-postgres`)
# so it reuses our `connect`/default-host logic and connection-task spawning.
# `rt_tokio_1` lets the pool enforce checkout timeouts (it sleeps via tokio time),
# which we drive on our own tokio runtime.
deadpool = { version = "0.12", features = ["rt_tokio_1"] }
once_cell = "1.18.0"
# Fast hashing for the integer-keyed maps in state resolution.
rustc-hash = "2.1.1"
itertools = "0.15.0"
# Used by the `libpq` module to load the system libpq at runtime, so that
# libpq is an optional runtime dependency rather than a build-time one.
libloading = "0.8"
postgres-protocol = "0.6.10"
# Use the `ring` crypto provider (not the default `aws-lc-rs`, which needs cmake
# and isn't available here) — `ring` is already in the tree via reqwest.
rustls = { version = "0.23", default-features = false, features = [
"ring",
"logging",
"std",
"tls12",
] }
rustls-native-certs = "0.8"
rustls-pemfile = "2"
tokio-postgres-rustls = { version = "0.14.0", default-features = false, features = [
"ring",
] }
lru = "0.16.4"
# Outbound federation (`federation::agent`). We drive hyper's connection pool
# with our own connector, which does Matrix server name resolution, the IP
# range policy and the TLS policy.
hyper = { version = "1.6.0", features = ["client", "http1"] }
hyper-util = { version = "0.1.16", features = [
"client",
"client-legacy",
"http1",
"tokio",
] }
tokio-rustls = { version = "0.26.2", default-features = false, features = [
"ring",
"logging",
"tls12",
] }
tower-service = "0.3.3"
# SRV lookups. A/AAAA go through the system resolver, as in Python. 0.25
# rather than 0.26, which needs a newer rustc than our MSRV.
hickory-resolver = { version = "0.25.2", default-features = false, features = [
"tokio",
"system-config",
] }
# SRV record ordering and cache period jitter.
rand = "0.10.2"
# The `Expires` header of `.well-known` responses.
httpdate = "1.0.3"
# Resolving `.well-known` redirects.
url = "2.5.4"
# Signing outbound federation requests. 2.x rather than 3.x, which needs a
# newer rustc than our MSRV.
ed25519-dalek = "2.2.0"
# The IP range lists in config.
ipnet = "2.11.0"
[dev-dependencies]
tokio = { version = "1.44.2", features = ["macros", "test-util"] }
[build-dependencies]
blake2 = "0.11.0"
hex = "0.4.3"
rustc_version = "0.4.1"