Remove polylith/API mode (#2967)

This removes most of the code used for polylith/API mode.

This removes the `/api` internal endpoints entirely. 

Binary size change roughly 5%: 
```
51437560 Feb 13 10:15 dendrite-monolith-server # old
48759008 Feb 13 10:15 dendrite-monolith-server # new
```
This commit is contained in:
Till 2023-02-14 12:47:47 +01:00 committed by GitHub
parent cc59879faa
commit 11d9b9db0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
106 changed files with 374 additions and 5850 deletions

View file

@ -17,7 +17,6 @@ see: https://www.matrix.org/security-disclosure-policy/
### Background information ### Background information
<!-- Please include versions of all software when known e.g database versions, docker versions, client versions --> <!-- Please include versions of all software when known e.g database versions, docker versions, client versions -->
- **Dendrite version or git SHA**: - **Dendrite version or git SHA**:
- **Monolith or Polylith?**:
- **SQLite3 or Postgres?**: - **SQLite3 or Postgres?**:
- **Running in Docker?**: - **Running in Docker?**:
- **`go version`**: - **`go version`**:

View file

@ -25,7 +25,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: "stable"
cache: true cache: true
- name: Install Node - name: Install Node
@ -62,14 +62,14 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: "stable"
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v3 uses: golangci/golangci-lint-action@v3
# run go test with different go versions # run go test with different go versions
test: test:
timeout-minutes: 10 timeout-minutes: 10
name: Unit tests (Go ${{ matrix.go }}) name: Unit tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
# Service containers to run with `container-job` # Service containers to run with `container-job`
services: services:
@ -91,25 +91,21 @@ jobs:
--health-interval 10s --health-interval 10s
--health-timeout 5s --health-timeout 5s
--health-retries 5 --health-retries 5
strategy:
fail-fast: false
matrix:
go: ["1.19"]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup go - name: Setup go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: ${{ matrix.go }} go-version: "stable"
- uses: actions/cache@v3 - uses: actions/cache@v3
# manually set up caches, as they otherwise clash with different steps using setup-go with cache=true # manually set up caches, as they otherwise clash with different steps using setup-go with cache=true
with: with:
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
key: ${{ runner.os }}-go${{ matrix.go }}-unit-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-stable-unit-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
${{ runner.os }}-go${{ matrix.go }}-unit- ${{ runner.os }}-go-stable-unit-
- name: Set up gotestfmt - name: Set up gotestfmt
uses: gotesttools/gotestfmt-action@v2 uses: gotesttools/gotestfmt-action@v2
with: with:
@ -130,7 +126,6 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
go: ["1.18", "1.19", "1.20.0"]
goos: ["linux"] goos: ["linux"]
goarch: ["amd64", "386"] goarch: ["amd64", "386"]
steps: steps:
@ -138,15 +133,15 @@ jobs:
- name: Setup go - name: Setup go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: ${{ matrix.go }} go-version: "stable"
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
key: ${{ runner.os }}-go${{ matrix.go }}${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-stable-${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
key: ${{ runner.os }}-go${{ matrix.go }}${{ matrix.goos }}-${{ matrix.goarch }}- key: ${{ runner.os }}-go-stable-${{ matrix.goos }}-${{ matrix.goarch }}-
- name: Install dependencies x86 - name: Install dependencies x86
if: ${{ matrix.goarch == '386' }} if: ${{ matrix.goarch == '386' }}
run: sudo apt update && sudo apt-get install -y gcc-multilib run: sudo apt update && sudo apt-get install -y gcc-multilib
@ -164,23 +159,22 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
go: ["1.18", "1.19", "1.20.0"]
goos: ["windows"] goos: ["windows"]
goarch: ["amd64"] goarch: ["amd64"]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup Go ${{ matrix.go }} - name: Setup Go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: ${{ matrix.go }} go-version: "stable"
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
key: ${{ runner.os }}-go${{ matrix.go }}${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-stable-${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
key: ${{ runner.os }}-go${{ matrix.go }}${{ matrix.goos }}-${{ matrix.goarch }}- key: ${{ runner.os }}-go-stable-${{ matrix.goos }}-${{ matrix.goarch }}-
- name: Install dependencies - name: Install dependencies
run: sudo apt update && sudo apt install -y gcc-mingw-w64-x86-64 # install required gcc run: sudo apt update && sudo apt install -y gcc-mingw-w64-x86-64 # install required gcc
- env: - env:
@ -206,7 +200,7 @@ jobs:
integration: integration:
timeout-minutes: 20 timeout-minutes: 20
needs: initial-tests-done needs: initial-tests-done
name: Integration tests (Go ${{ matrix.go }}) name: Integration tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
# Service containers to run with `container-job` # Service containers to run with `container-job`
services: services:
@ -228,16 +222,12 @@ jobs:
--health-interval 10s --health-interval 10s
--health-timeout 5s --health-timeout 5s
--health-retries 5 --health-retries 5
strategy:
fail-fast: false
matrix:
go: ["1.19"]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup go - name: Setup go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: ${{ matrix.go }} go-version: "stable"
- name: Set up gotestfmt - name: Set up gotestfmt
uses: gotesttools/gotestfmt-action@v2 uses: gotesttools/gotestfmt-action@v2
with: with:
@ -248,9 +238,9 @@ jobs:
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
key: ${{ runner.os }}-go${{ matrix.go }}-test-race-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-stable-test-race-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
${{ runner.os }}-go${{ matrix.go }}-test-race- ${{ runner.os }}-go-stable-test-race-
- run: go test -race -json -v -coverpkg=./... -coverprofile=cover.out $(go list ./... | grep -v /cmd/dendrite*) 2>&1 | gotestfmt - run: go test -race -json -v -coverpkg=./... -coverprofile=cover.out $(go list ./... | grep -v /cmd/dendrite*) 2>&1 | gotestfmt
env: env:
POSTGRES_HOST: localhost POSTGRES_HOST: localhost
@ -261,6 +251,7 @@ jobs:
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v3
with: with:
flags: unittests flags: unittests
fail_ci_if_error: true
# run database upgrade tests # run database upgrade tests
upgrade_test: upgrade_test:
@ -273,7 +264,7 @@ jobs:
- name: Setup go - name: Setup go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: "1.18" go-version: "stable"
cache: true cache: true
- name: Build upgrade-tests - name: Build upgrade-tests
run: go build ./cmd/dendrite-upgrade-tests run: go build ./cmd/dendrite-upgrade-tests
@ -293,7 +284,7 @@ jobs:
- name: Setup go - name: Setup go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: "1.18" go-version: "stable"
cache: true cache: true
- name: Build upgrade-tests - name: Build upgrade-tests
run: go build ./cmd/dendrite-upgrade-tests run: go build ./cmd/dendrite-upgrade-tests
@ -317,19 +308,9 @@ jobs:
- label: SQLite Cgo - label: SQLite Cgo
cgo: 1 cgo: 1
- label: SQLite native, full HTTP APIs
api: full-http
- label: SQLite Cgo, full HTTP APIs
api: full-http
cgo: 1
- label: PostgreSQL - label: PostgreSQL
postgres: postgres postgres: postgres
- label: PostgreSQL, full HTTP APIs
postgres: postgres
api: full-http
container: container:
image: matrixdotorg/sytest-dendrite image: matrixdotorg/sytest-dendrite
volumes: volumes:
@ -338,7 +319,6 @@ jobs:
- /root/.cache/go-mod:/gopath/pkg/mod - /root/.cache/go-mod:/gopath/pkg/mod
env: env:
POSTGRES: ${{ matrix.postgres && 1}} POSTGRES: ${{ matrix.postgres && 1}}
API: ${{ matrix.api && 1 }}
SYTEST_BRANCH: ${{ github.head_ref }} SYTEST_BRANCH: ${{ github.head_ref }}
CGO_ENABLED: ${{ matrix.cgo && 1 }} CGO_ENABLED: ${{ matrix.cgo && 1 }}
steps: steps:
@ -390,22 +370,9 @@ jobs:
- label: SQLite Cgo - label: SQLite Cgo
cgo: 1 cgo: 1
- label: SQLite native, full HTTP APIs
api: full-http
cgo: 0
- label: SQLite Cgo, full HTTP APIs
api: full-http
cgo: 1
- label: PostgreSQL - label: PostgreSQL
postgres: Postgres postgres: Postgres
cgo: 0 cgo: 0
- label: PostgreSQL, full HTTP APIs
postgres: Postgres
api: full-http
cgo: 0
steps: steps:
# Env vars are set file a file given by $GITHUB_PATH. We need both Go 1.17 and GOPATH on env to run Complement. # Env vars are set file a file given by $GITHUB_PATH. We need both Go 1.17 and GOPATH on env to run Complement.
# See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path # See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path
@ -447,7 +414,7 @@ jobs:
(wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break (wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break
done done
# Build initial Dendrite image # Build initial Dendrite image
- run: docker build --build-arg=CGO=${{ matrix.cgo }} -t complement-dendrite:${{ matrix.postgres }}${{ matrix.api }}${{ matrix.cgo }} -f build/scripts/Complement${{ matrix.postgres }}.Dockerfile . - run: docker build --build-arg=CGO=${{ matrix.cgo }} -t complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }} -f build/scripts/Complement${{ matrix.postgres }}.Dockerfile .
working-directory: dendrite working-directory: dendrite
env: env:
DOCKER_BUILDKIT: 1 DOCKER_BUILDKIT: 1
@ -459,8 +426,7 @@ jobs:
shell: bash shell: bash
name: Run Complement Tests name: Run Complement Tests
env: env:
COMPLEMENT_BASE_IMAGE: complement-dendrite:${{ matrix.postgres }}${{ matrix.api }}${{ matrix.cgo }} COMPLEMENT_BASE_IMAGE: complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }}
COMPLEMENT_DENDRITE_API: ${{ matrix.api && 1 }}
COMPLEMENT_SHARE_ENV_PREFIX: COMPLEMENT_DENDRITE_ COMPLEMENT_SHARE_ENV_PREFIX: COMPLEMENT_DENDRITE_
working-directory: complement working-directory: complement

View file

@ -61,7 +61,6 @@ jobs:
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
context: . context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }} build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
target: monolith
platforms: ${{ env.PLATFORMS }} platforms: ${{ env.PLATFORMS }}
push: true push: true
tags: | tags: |
@ -77,7 +76,6 @@ jobs:
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
context: . context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }} build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
target: monolith
platforms: ${{ env.PLATFORMS }} platforms: ${{ env.PLATFORMS }}
push: true push: true
tags: | tags: |
@ -98,86 +96,6 @@ jobs:
with: with:
sarif_file: "trivy-results.sarif" sarif_file: "trivy-results.sarif"
polylith:
name: Polylith image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
security-events: write # To upload Trivy sarif files
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Get release tag & build flags
if: github.event_name == 'release' # Only for GitHub releases
run: |
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
echo "BUILD=$(git rev-parse --short HEAD || \"\")" >> $GITHUB_ENV
BRANCH=$(git symbolic-ref --short HEAD | tr -d \/)
[ ${BRANCH} == "main" ] && BRANCH=""
echo "BRANCH=${BRANCH}" >> $GITHUB_ENV
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ env.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Login to GitHub Containers
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build main polylith image
if: github.ref_name == 'main'
id: docker_build_polylith
uses: docker/build-push-action@v3
with:
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
target: polylith
platforms: ${{ env.PLATFORMS }}
push: true
tags: |
${{ env.DOCKER_NAMESPACE }}/dendrite-polylith:${{ github.ref_name }}
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-polylith:${{ github.ref_name }}
- name: Build release polylith image
if: github.event_name == 'release' # Only for GitHub releases
id: docker_build_polylith_release
uses: docker/build-push-action@v3
with:
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
target: polylith
platforms: ${{ env.PLATFORMS }}
push: true
tags: |
${{ env.DOCKER_NAMESPACE }}/dendrite-polylith:latest
${{ env.DOCKER_NAMESPACE }}/dendrite-polylith:${{ env.RELEASE_VERSION }}
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-polylith:latest
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-polylith:${{ env.RELEASE_VERSION }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-polylith:${{ github.ref_name }}
format: "sarif"
output: "trivy-results.sarif"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: "trivy-results.sarif"
demo-pinecone: demo-pinecone:
name: Pinecone demo image name: Pinecone demo image
runs-on: ubuntu-latest runs-on: ubuntu-latest

View file

@ -24,19 +24,8 @@ jobs:
- label: SQLite Cgo - label: SQLite Cgo
cgo: 1 cgo: 1
- label: SQLite native, full HTTP APIs
api: full-http
- label: SQLite Cgo, full HTTP APIs
api: full-http
cgo: 1
- label: PostgreSQL - label: PostgreSQL
postgres: postgres postgres: postgres
- label: PostgreSQL, full HTTP APIs
postgres: postgres
api: full-http
container: container:
image: matrixdotorg/sytest-dendrite:latest image: matrixdotorg/sytest-dendrite:latest
volumes: volumes:
@ -45,7 +34,6 @@ jobs:
- /root/.cache/go-mod:/gopath/pkg/mod - /root/.cache/go-mod:/gopath/pkg/mod
env: env:
POSTGRES: ${{ matrix.postgres && 1}} POSTGRES: ${{ matrix.postgres && 1}}
API: ${{ matrix.api && 1 }}
SYTEST_BRANCH: ${{ github.head_ref }} SYTEST_BRANCH: ${{ github.head_ref }}
RACE_DETECTION: 1 RACE_DETECTION: 1
COVER: 1 COVER: 1
@ -93,7 +81,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: '>=1.19.0' go-version: 'stable'
cache: true cache: true
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
@ -125,22 +113,9 @@ jobs:
- label: SQLite Cgo - label: SQLite Cgo
cgo: 1 cgo: 1
- label: SQLite native, full HTTP APIs
api: full-http
cgo: 0
- label: SQLite Cgo, full HTTP APIs
api: full-http
cgo: 1
- label: PostgreSQL - label: PostgreSQL
postgres: Postgres postgres: Postgres
cgo: 0 cgo: 0
- label: PostgreSQL, full HTTP APIs
postgres: Postgres
api: full-http
cgo: 0
steps: steps:
# Env vars are set file a file given by $GITHUB_PATH. We need both Go 1.17 and GOPATH on env to run Complement. # Env vars are set file a file given by $GITHUB_PATH. We need both Go 1.17 and GOPATH on env to run Complement.
# See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path # See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path
@ -182,7 +157,7 @@ jobs:
(wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break (wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break
done done
# Build initial Dendrite image # Build initial Dendrite image
- run: docker build --build-arg=CGO=${{ matrix.cgo }} -t complement-dendrite:${{ matrix.postgres }}${{ matrix.api }}${{ matrix.cgo }} -f build/scripts/Complement${{ matrix.postgres }}.Dockerfile . - run: docker build --build-arg=CGO=${{ matrix.cgo }} -t complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }} -f build/scripts/Complement${{ matrix.postgres }}.Dockerfile .
working-directory: dendrite working-directory: dendrite
env: env:
DOCKER_BUILDKIT: 1 DOCKER_BUILDKIT: 1
@ -203,8 +178,7 @@ jobs:
shell: bash shell: bash
name: Run Complement Tests name: Run Complement Tests
env: env:
COMPLEMENT_BASE_IMAGE: complement-dendrite:${{ matrix.postgres }}${{ matrix.api }}${{ matrix.cgo }} COMPLEMENT_BASE_IMAGE: complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }}
COMPLEMENT_DENDRITE_API: ${{ matrix.api && 1 }}
COMPLEMENT_SHARE_ENV_PREFIX: COMPLEMENT_DENDRITE_ COMPLEMENT_SHARE_ENV_PREFIX: COMPLEMENT_DENDRITE_
COMPLEMENT_DENDRITE_COVER: 1 COMPLEMENT_DENDRITE_COVER: 1
COMPLEMENT_POST_TEST_SCRIPT: /tmp/posttest.sh COMPLEMENT_POST_TEST_SCRIPT: /tmp/posttest.sh
@ -229,7 +203,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: '>=1.19.0' go-version: 'stable'
cache: true cache: true
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3

View file

@ -3,7 +3,7 @@
# #
# base installs required dependencies and runs go mod download to cache dependencies # base installs required dependencies and runs go mod download to cache dependencies
# #
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.19-alpine AS base FROM --platform=${BUILDPLATFORM} docker.io/golang:1.20-alpine AS base
RUN apk --update --no-cache add bash build-base curl RUN apk --update --no-cache add bash build-base curl
# #
@ -23,44 +23,27 @@ RUN --mount=target=. \
CGO_ENABLED=$([ "$TARGETARCH" = "$USERARCH" ] && echo "1" || echo "0") \ CGO_ENABLED=$([ "$TARGETARCH" = "$USERARCH" ] && echo "1" || echo "0") \
go build -v -ldflags="${FLAGS}" -trimpath -o /out/ ./cmd/... go build -v -ldflags="${FLAGS}" -trimpath -o /out/ ./cmd/...
# #
# The dendrite base image # Builds the Dendrite image containing all required binaries
# #
FROM alpine:latest AS dendrite-base FROM alpine:latest
RUN apk --update --no-cache add curl RUN apk --update --no-cache add curl
LABEL org.opencontainers.image.title="Dendrite"
LABEL org.opencontainers.image.description="Next-generation Matrix homeserver written in Go" LABEL org.opencontainers.image.description="Next-generation Matrix homeserver written in Go"
LABEL org.opencontainers.image.source="https://github.com/matrix-org/dendrite" LABEL org.opencontainers.image.source="https://github.com/matrix-org/dendrite"
LABEL org.opencontainers.image.licenses="Apache-2.0" LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL org.opencontainers.image.documentation="https://matrix-org.github.io/dendrite/" LABEL org.opencontainers.image.documentation="https://matrix-org.github.io/dendrite/"
LABEL org.opencontainers.image.vendor="The Matrix.org Foundation C.I.C." LABEL org.opencontainers.image.vendor="The Matrix.org Foundation C.I.C."
#
# Builds the polylith image and only contains the polylith binary
#
FROM dendrite-base AS polylith
LABEL org.opencontainers.image.title="Dendrite (Polylith)"
COPY --from=build /out/dendrite-polylith-multi /usr/bin/
VOLUME /etc/dendrite
WORKDIR /etc/dendrite
ENTRYPOINT ["/usr/bin/dendrite-polylith-multi"]
#
# Builds the monolith image and contains all required binaries
#
FROM dendrite-base AS monolith
LABEL org.opencontainers.image.title="Dendrite (Monolith)"
COPY --from=build /out/create-account /usr/bin/create-account COPY --from=build /out/create-account /usr/bin/create-account
COPY --from=build /out/generate-config /usr/bin/generate-config COPY --from=build /out/generate-config /usr/bin/generate-config
COPY --from=build /out/generate-keys /usr/bin/generate-keys COPY --from=build /out/generate-keys /usr/bin/generate-keys
COPY --from=build /out/dendrite-monolith-server /usr/bin/dendrite-monolith-server COPY --from=build /out/dendrite /usr/bin/dendrite
VOLUME /etc/dendrite VOLUME /etc/dendrite
WORKDIR /etc/dendrite WORKDIR /etc/dendrite
ENTRYPOINT ["/usr/bin/dendrite-monolith-server"] ENTRYPOINT ["/usr/bin/dendrite"]
EXPOSE 8008 8448 EXPOSE 8008 8448

View file

@ -24,7 +24,6 @@ This does not mean:
- Dendrite is ready for massive homeserver deployments. There is no sharding of microservices (although it is possible to run them on separate machines) and there is no high-availability/clustering support. - Dendrite is ready for massive homeserver deployments. There is no sharding of microservices (although it is possible to run them on separate machines) and there is no high-availability/clustering support.
Currently, we expect Dendrite to function well for small (10s/100s of users) homeserver deployments as well as P2P Matrix nodes in-browser or on mobile devices. Currently, we expect Dendrite to function well for small (10s/100s of users) homeserver deployments as well as P2P Matrix nodes in-browser or on mobile devices.
In the future, we will be able to scale up to gigantic servers (equivalent to `matrix.org`) via polylith mode.
If you have further questions, please take a look at [our FAQ](docs/FAQ.md) or join us in: If you have further questions, please take a look at [our FAQ](docs/FAQ.md) or join us in:

View file

@ -21,14 +21,12 @@ import (
"sync" "sync"
"time" "time"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
appserviceAPI "github.com/matrix-org/dendrite/appservice/api" appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
"github.com/matrix-org/dendrite/appservice/consumers" "github.com/matrix-org/dendrite/appservice/consumers"
"github.com/matrix-org/dendrite/appservice/inthttp"
"github.com/matrix-org/dendrite/appservice/query" "github.com/matrix-org/dendrite/appservice/query"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/setup/base" "github.com/matrix-org/dendrite/setup/base"
@ -36,11 +34,6 @@ import (
userapi "github.com/matrix-org/dendrite/userapi/api" userapi "github.com/matrix-org/dendrite/userapi/api"
) )
// AddInternalRoutes registers HTTP handlers for internal API calls
func AddInternalRoutes(router *mux.Router, queryAPI appserviceAPI.AppServiceInternalAPI, enableMetrics bool) {
inthttp.AddRoutes(queryAPI, router, enableMetrics)
}
// NewInternalAPI returns a concerete implementation of the internal API. Callers // NewInternalAPI returns a concerete implementation of the internal API. Callers
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes. // can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
func NewInternalAPI( func NewInternalAPI(

View file

@ -10,12 +10,8 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/gorilla/mux"
"github.com/matrix-org/dendrite/appservice" "github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/appservice/api" "github.com/matrix-org/dendrite/appservice/api"
"github.com/matrix-org/dendrite/appservice/inthttp"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/roomserver" "github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/test" "github.com/matrix-org/dendrite/test"
@ -132,23 +128,7 @@ func TestAppserviceInternalAPI(t *testing.T) {
usrAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, nil, rsAPI, nil) usrAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, nil, rsAPI, nil)
asAPI := appservice.NewInternalAPI(base, usrAPI, rsAPI) asAPI := appservice.NewInternalAPI(base, usrAPI, rsAPI)
// Finally execute the tests runCases(t, asAPI)
t.Run("HTTP API", func(t *testing.T) {
router := mux.NewRouter().PathPrefix(httputil.InternalPathPrefix).Subrouter()
appservice.AddInternalRoutes(router, asAPI, base.EnableMetrics)
apiURL, cancel := test.ListenAndServe(t, router, false)
defer cancel()
asHTTPApi, err := inthttp.NewAppserviceClient(apiURL, &http.Client{})
if err != nil {
t.Fatalf("failed to create HTTP client: %s", err)
}
runCases(t, asHTTPApi)
})
t.Run("Monolith", func(t *testing.T) {
runCases(t, asAPI)
})
}) })
} }

View file

@ -1,84 +0,0 @@
package inthttp
import (
"context"
"errors"
"net/http"
"github.com/matrix-org/dendrite/appservice/api"
"github.com/matrix-org/dendrite/internal/httputil"
)
// HTTP paths for the internal HTTP APIs
const (
AppServiceRoomAliasExistsPath = "/appservice/RoomAliasExists"
AppServiceUserIDExistsPath = "/appservice/UserIDExists"
AppServiceLocationsPath = "/appservice/locations"
AppServiceUserPath = "/appservice/users"
AppServiceProtocolsPath = "/appservice/protocols"
)
// httpAppServiceQueryAPI contains the URL to an appservice query API and a
// reference to a httpClient used to reach it
type httpAppServiceQueryAPI struct {
appserviceURL string
httpClient *http.Client
}
// NewAppserviceClient creates a AppServiceQueryAPI implemented by talking
// to a HTTP POST API.
// If httpClient is nil an error is returned
func NewAppserviceClient(
appserviceURL string,
httpClient *http.Client,
) (api.AppServiceInternalAPI, error) {
if httpClient == nil {
return nil, errors.New("NewRoomserverAliasAPIHTTP: httpClient is <nil>")
}
return &httpAppServiceQueryAPI{appserviceURL, httpClient}, nil
}
// RoomAliasExists implements AppServiceQueryAPI
func (h *httpAppServiceQueryAPI) RoomAliasExists(
ctx context.Context,
request *api.RoomAliasExistsRequest,
response *api.RoomAliasExistsResponse,
) error {
return httputil.CallInternalRPCAPI(
"RoomAliasExists", h.appserviceURL+AppServiceRoomAliasExistsPath,
h.httpClient, ctx, request, response,
)
}
// UserIDExists implements AppServiceQueryAPI
func (h *httpAppServiceQueryAPI) UserIDExists(
ctx context.Context,
request *api.UserIDExistsRequest,
response *api.UserIDExistsResponse,
) error {
return httputil.CallInternalRPCAPI(
"UserIDExists", h.appserviceURL+AppServiceUserIDExistsPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpAppServiceQueryAPI) Locations(ctx context.Context, request *api.LocationRequest, response *api.LocationResponse) error {
return httputil.CallInternalRPCAPI(
"ASLocation", h.appserviceURL+AppServiceLocationsPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpAppServiceQueryAPI) User(ctx context.Context, request *api.UserRequest, response *api.UserResponse) error {
return httputil.CallInternalRPCAPI(
"ASUser", h.appserviceURL+AppServiceUserPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpAppServiceQueryAPI) Protocols(ctx context.Context, request *api.ProtocolRequest, response *api.ProtocolResponse) error {
return httputil.CallInternalRPCAPI(
"ASProtocols", h.appserviceURL+AppServiceProtocolsPath,
h.httpClient, ctx, request, response,
)
}

View file

@ -1,36 +0,0 @@
package inthttp
import (
"github.com/gorilla/mux"
"github.com/matrix-org/dendrite/appservice/api"
"github.com/matrix-org/dendrite/internal/httputil"
)
// AddRoutes adds the AppServiceQueryAPI handlers to the http.ServeMux.
func AddRoutes(a api.AppServiceInternalAPI, internalAPIMux *mux.Router, enableMetrics bool) {
internalAPIMux.Handle(
AppServiceRoomAliasExistsPath,
httputil.MakeInternalRPCAPI("AppserviceRoomAliasExists", enableMetrics, a.RoomAliasExists),
)
internalAPIMux.Handle(
AppServiceUserIDExistsPath,
httputil.MakeInternalRPCAPI("AppserviceUserIDExists", enableMetrics, a.UserIDExists),
)
internalAPIMux.Handle(
AppServiceProtocolsPath,
httputil.MakeInternalRPCAPI("AppserviceProtocols", enableMetrics, a.Protocols),
)
internalAPIMux.Handle(
AppServiceLocationsPath,
httputil.MakeInternalRPCAPI("AppserviceLocations", enableMetrics, a.Locations),
)
internalAPIMux.Handle(
AppServiceUserPath,
httputil.MakeInternalRPCAPI("AppserviceUser", enableMetrics, a.User),
)
}

View file

@ -177,7 +177,7 @@ func startup() {
if err := cfg.Derive(); err != nil { if err := cfg.Derive(); err != nil {
logrus.Fatalf("Failed to derive values from config: %s", err) logrus.Fatalf("Failed to derive values from config: %s", err)
} }
base := base.NewBaseDendrite(cfg, "Monolith") base := base.NewBaseDendrite(cfg)
defer base.Close() // nolint: errcheck defer base.Close() // nolint: errcheck
rsAPI := roomserver.NewInternalAPI(base) rsAPI := roomserver.NewInternalAPI(base)
@ -215,7 +215,6 @@ func startup() {
monolith.AddAllPublicRoutes(base) monolith.AddAllPublicRoutes(base)
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath() httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
httpRouter.PathPrefix(httputil.InternalPathPrefix).Handler(base.InternalAPIMux)
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux) httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux) httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)

View file

@ -5,7 +5,6 @@ These are Docker images for Dendrite!
They can be found on Docker Hub: They can be found on Docker Hub:
- [matrixdotorg/dendrite-monolith](https://hub.docker.com/r/matrixdotorg/dendrite-monolith) for monolith deployments - [matrixdotorg/dendrite-monolith](https://hub.docker.com/r/matrixdotorg/dendrite-monolith) for monolith deployments
- [matrixdotorg/dendrite-polylith](https://hub.docker.com/r/matrixdotorg/dendrite-polylith) for polylith deployments
## Dockerfiles ## Dockerfiles
@ -15,7 +14,6 @@ repository, run:
``` ```
docker build . --target monolith -t matrixdotorg/dendrite-monolith docker build . --target monolith -t matrixdotorg/dendrite-monolith
docker build . --target polylith -t matrixdotorg/dendrite-monolith
docker build . --target demo-pinecone -t matrixdotorg/dendrite-demo-pinecone docker build . --target demo-pinecone -t matrixdotorg/dendrite-demo-pinecone
docker build . --target demo-yggdrasil -t matrixdotorg/dendrite-demo-yggdrasil docker build . --target demo-yggdrasil -t matrixdotorg/dendrite-demo-yggdrasil
``` ```
@ -25,7 +23,6 @@ docker build . --target demo-yggdrasil -t matrixdotorg/dendrite-demo-yggdrasil
There are two sample `docker-compose` files: There are two sample `docker-compose` files:
- `docker-compose.monolith.yml` which runs a monolith Dendrite deployment - `docker-compose.monolith.yml` which runs a monolith Dendrite deployment
- `docker-compose.polylith.yml` which runs a polylith Dendrite deployment
## Configuration ## Configuration
@ -51,7 +48,7 @@ docker run --rm --entrypoint="" \
The key files will now exist in your current working directory, and can be mounted into place. The key files will now exist in your current working directory, and can be mounted into place.
## Starting Dendrite as a monolith deployment ## Starting Dendrite
Create your config based on the [`dendrite-sample.monolith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.monolith.yaml) sample configuration file. Create your config based on the [`dendrite-sample.monolith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.monolith.yaml) sample configuration file.
@ -61,16 +58,6 @@ Then start the deployment:
docker-compose -f docker-compose.monolith.yml up docker-compose -f docker-compose.monolith.yml up
``` ```
## Starting Dendrite as a polylith deployment
Create your config based on the [`dendrite-sample.polylith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.polylith.yaml) sample configuration file.
Then start the deployment:
```
docker-compose -f docker-compose.polylith.yml up
```
## Building the images ## Building the images
The `build/docker/images-build.sh` script will build the base image, followed by The `build/docker/images-build.sh` script will build the base image, followed by

View file

@ -1,143 +0,0 @@
version: "3.4"
services:
postgres:
hostname: postgres
image: postgres:14
restart: always
volumes:
- ./postgres/create_db.sh:/docker-entrypoint-initdb.d/20-create_db.sh
# To persist your PostgreSQL databases outside of the Docker image,
# to prevent data loss, modify the following ./path_to path:
- ./path_to/postgresql:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: itsasecret
POSTGRES_USER: dendrite
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dendrite"]
interval: 5s
timeout: 5s
retries: 5
networks:
- internal
jetstream:
hostname: jetstream
image: nats:latest
command: |
--jetstream
--store_dir /var/lib/nats
--cluster_name Dendrite
volumes:
# To persist your NATS JetStream streams outside of the Docker image,
# prevent data loss, modify the following ./path_to path:
- ./path_to/nats:/var/lib/nats
networks:
- internal
client_api:
hostname: client_api
image: matrixdotorg/dendrite-polylith:latest
command: clientapi
volumes:
- ./config:/etc/dendrite
depends_on:
- jetstream
- postgres
networks:
- internal
restart: unless-stopped
media_api:
hostname: media_api
image: matrixdotorg/dendrite-polylith:latest
command: mediaapi
volumes:
- ./config:/etc/dendrite
- ./media:/var/dendrite/media
networks:
- internal
restart: unless-stopped
sync_api:
hostname: sync_api
image: matrixdotorg/dendrite-polylith:latest
command: syncapi
volumes:
- ./config:/etc/dendrite
depends_on:
- jetstream
- postgres
networks:
- internal
restart: unless-stopped
room_server:
hostname: room_server
image: matrixdotorg/dendrite-polylith:latest
command: roomserver
volumes:
- ./config:/etc/dendrite
depends_on:
- jetstream
- postgres
networks:
- internal
restart: unless-stopped
federation_api:
hostname: federation_api
image: matrixdotorg/dendrite-polylith:latest
command: federationapi
volumes:
- ./config:/etc/dendrite
depends_on:
- jetstream
- postgres
networks:
- internal
restart: unless-stopped
key_server:
hostname: key_server
image: matrixdotorg/dendrite-polylith:latest
command: keyserver
volumes:
- ./config:/etc/dendrite
depends_on:
- jetstream
- postgres
networks:
- internal
restart: unless-stopped
user_api:
hostname: user_api
image: matrixdotorg/dendrite-polylith:latest
command: userapi
volumes:
- ./config:/etc/dendrite
depends_on:
- jetstream
- postgres
networks:
- internal
restart: unless-stopped
appservice_api:
hostname: appservice_api
image: matrixdotorg/dendrite-polylith:latest
command: appservice
volumes:
- ./config:/etc/dendrite
networks:
- internal
depends_on:
- jetstream
- postgres
- room_server
- user_api
restart: unless-stopped
networks:
internal:
attachable: true

View file

@ -7,6 +7,5 @@ TAG=${1:-latest}
echo "Building tag '${TAG}'" echo "Building tag '${TAG}'"
docker build . --target monolith -t matrixdotorg/dendrite-monolith:${TAG} docker build . --target monolith -t matrixdotorg/dendrite-monolith:${TAG}
docker build . --target polylith -t matrixdotorg/dendrite-monolith:${TAG}
docker build . --target demo-pinecone -t matrixdotorg/dendrite-demo-pinecone:${TAG} docker build . --target demo-pinecone -t matrixdotorg/dendrite-demo-pinecone:${TAG}
docker build . --target demo-yggdrasil -t matrixdotorg/dendrite-demo-yggdrasil:${TAG} docker build . --target demo-yggdrasil -t matrixdotorg/dendrite-demo-yggdrasil:${TAG}

View file

@ -5,4 +5,3 @@ TAG=${1:-latest}
echo "Pulling tag '${TAG}'" echo "Pulling tag '${TAG}'"
docker pull matrixdotorg/dendrite-monolith:${TAG} docker pull matrixdotorg/dendrite-monolith:${TAG}
docker pull matrixdotorg/dendrite-polylith:${TAG}

View file

@ -5,4 +5,3 @@ TAG=${1:-latest}
echo "Pushing tag '${TAG}'" echo "Pushing tag '${TAG}'"
docker push matrixdotorg/dendrite-monolith:${TAG} docker push matrixdotorg/dendrite-monolith:${TAG}
docker push matrixdotorg/dendrite-polylith:${TAG}

View file

@ -127,8 +127,8 @@ func (m *DendriteMonolith) Start() {
cfg := &config.Dendrite{} cfg := &config.Dendrite{}
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: true,
}) })
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk)) cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
cfg.Global.PrivateKey = sk cfg.Global.PrivateKey = sk
@ -149,7 +149,7 @@ func (m *DendriteMonolith) Start() {
panic(err) panic(err)
} }
base := base.NewBaseDendrite(cfg, "Monolith") base := base.NewBaseDendrite(cfg)
base.ConfigureAdminEndpoints() base.ConfigureAdminEndpoints()
m.processContext = base.ProcessContext m.processContext = base.ProcessContext
defer base.Close() // nolint: errcheck defer base.Close() // nolint: errcheck
@ -194,7 +194,6 @@ func (m *DendriteMonolith) Start() {
monolith.AddAllPublicRoutes(base) monolith.AddAllPublicRoutes(base)
httpRouter := mux.NewRouter() httpRouter := mux.NewRouter()
httpRouter.PathPrefix(httputil.InternalPathPrefix).Handler(base.InternalAPIMux)
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux) httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux) httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux) httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux)

View file

@ -16,8 +16,8 @@ RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-config && \ CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-config && \
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-keys && \ CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-keys && \
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/dendrite-monolith-server && \ CGO_ENABLED=${CGO} go build -o /dendrite/dendrite ./cmd/dendrite && \
CGO_ENABLED=${CGO} go test -c -cover -covermode=atomic -o /dendrite/dendrite-monolith-server-cover -coverpkg "github.com/matrix-org/..." ./cmd/dendrite-monolith-server && \ CGO_ENABLED=${CGO} go test -c -cover -covermode=atomic -o /dendrite/dendrite-cover -coverpkg "github.com/matrix-org/..." ./cmd/dendrite && \
cp build/scripts/complement-cmd.sh /complement-cmd.sh cp build/scripts/complement-cmd.sh /complement-cmd.sh
WORKDIR /dendrite WORKDIR /dendrite

View file

@ -19,13 +19,13 @@ WORKDIR /runtime
# This script compiles Dendrite for us. # This script compiles Dendrite for us.
RUN echo '\ RUN echo '\
#!/bin/bash -eux \n\ #!/bin/bash -eux \n\
if test -f "/runtime/dendrite-monolith-server" && test -f "/runtime/dendrite-monolith-server-cover"; then \n\ if test -f "/runtime/dendrite" && test -f "/runtime/dendrite-cover"; then \n\
echo "Skipping compilation; binaries exist" \n\ echo "Skipping compilation; binaries exist" \n\
exit 0 \n\ exit 0 \n\
fi \n\ fi \n\
cd /dendrite \n\ cd /dendrite \n\
go build -v -o /runtime /dendrite/cmd/dendrite-monolith-server \n\ go build -v -o /runtime /dendrite/cmd/dendrite \n\
go test -c -cover -covermode=atomic -o /runtime/dendrite-monolith-server-cover -coverpkg "github.com/matrix-org/..." /dendrite/cmd/dendrite-monolith-server \n\ go test -c -cover -covermode=atomic -o /runtime/dendrite-cover -coverpkg "github.com/matrix-org/..." /dendrite/cmd/dendrite \n\
' > compile.sh && chmod +x compile.sh ' > compile.sh && chmod +x compile.sh
# This script runs Dendrite for us. Must be run in the /runtime directory. # This script runs Dendrite for us. Must be run in the /runtime directory.
@ -35,8 +35,8 @@ RUN echo '\
./generate-keys -keysize 1024 --server $SERVER_NAME --tls-cert server.crt --tls-key server.key --tls-authority-cert /complement/ca/ca.crt --tls-authority-key /complement/ca/ca.key \n\ ./generate-keys -keysize 1024 --server $SERVER_NAME --tls-cert server.crt --tls-key server.key --tls-authority-cert /complement/ca/ca.crt --tls-authority-key /complement/ca/ca.key \n\
./generate-config -server $SERVER_NAME --ci > dendrite.yaml \n\ ./generate-config -server $SERVER_NAME --ci > dendrite.yaml \n\
cp /complement/ca/ca.crt /usr/local/share/ca-certificates/ && update-ca-certificates \n\ cp /complement/ca/ca.crt /usr/local/share/ca-certificates/ && update-ca-certificates \n\
[ ${COVER} -eq 1 ] && exec ./dendrite-monolith-server-cover --test.coverprofile=integrationcover.log --really-enable-open-registration --tls-cert server.crt --tls-key server.key --config dendrite.yaml \n\ [ ${COVER} -eq 1 ] && exec ./dendrite-cover --test.coverprofile=integrationcover.log --really-enable-open-registration --tls-cert server.crt --tls-key server.key --config dendrite.yaml \n\
exec ./dendrite-monolith-server --really-enable-open-registration --tls-cert server.crt --tls-key server.key --config dendrite.yaml \n\ exec ./dendrite --really-enable-open-registration --tls-cert server.crt --tls-key server.key --config dendrite.yaml \n\
' > run.sh && chmod +x run.sh ' > run.sh && chmod +x run.sh

View file

@ -34,8 +34,8 @@ RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-config && \ CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-config && \
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-keys && \ CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-keys && \
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/dendrite-monolith-server && \ CGO_ENABLED=${CGO} go build -o /dendrite/dendrite ./cmd/dendrite && \
CGO_ENABLED=${CGO} go test -c -cover -covermode=atomic -o /dendrite/dendrite-monolith-server-cover -coverpkg "github.com/matrix-org/..." ./cmd/dendrite-monolith-server && \ CGO_ENABLED=${CGO} go test -c -cover -covermode=atomic -o /dendrite/dendrite-cover -coverpkg "github.com/matrix-org/..." ./cmd/dendrite && \
cp build/scripts/complement-cmd.sh /complement-cmd.sh cp build/scripts/complement-cmd.sh /complement-cmd.sh
WORKDIR /dendrite WORKDIR /dendrite

View file

@ -4,19 +4,17 @@
if [[ "${COVER}" -eq 1 ]]; then if [[ "${COVER}" -eq 1 ]]; then
echo "Running with coverage" echo "Running with coverage"
exec /dendrite/dendrite-monolith-server-cover \ exec /dendrite/dendrite-cover \
--really-enable-open-registration \ --really-enable-open-registration \
--tls-cert server.crt \ --tls-cert server.crt \
--tls-key server.key \ --tls-key server.key \
--config dendrite.yaml \ --config dendrite.yaml \
-api=${API:-0} \
--test.coverprofile=complementcover.log --test.coverprofile=complementcover.log
else else
echo "Not running with coverage" echo "Not running with coverage"
exec /dendrite/dendrite-monolith-server \ exec /dendrite/dendrite \
--really-enable-open-registration \ --really-enable-open-registration \
--tls-cert server.crt \ --tls-cert server.crt \
--tls-key server.key \ --tls-key server.key \
--config dendrite.yaml \ --config dendrite.yaml
-api=${API:-0}
fi fi

View file

@ -22,7 +22,7 @@ func Test_AuthFallback(t *testing.T) {
for _, wantErr := range []bool{false, true} { for _, wantErr := range []bool{false, true} {
t.Run(fmt.Sprintf("useHCaptcha(%v) - recaptchaEnabled(%v) - wantErr(%v)", useHCaptcha, recaptchaEnabled, wantErr), func(t *testing.T) { t.Run(fmt.Sprintf("useHCaptcha(%v) - recaptchaEnabled(%v) - wantErr(%v)", useHCaptcha, recaptchaEnabled, wantErr), func(t *testing.T) {
// Set the defaults for each test // Set the defaults for each test
base.Cfg.ClientAPI.Defaults(config.DefaultOpts{Generate: true, Monolithic: true}) base.Cfg.ClientAPI.Defaults(config.DefaultOpts{Generate: true, SingleDatabase: true})
base.Cfg.ClientAPI.RecaptchaEnabled = recaptchaEnabled base.Cfg.ClientAPI.RecaptchaEnabled = recaptchaEnabled
base.Cfg.ClientAPI.RecaptchaPublicKey = "pub" base.Cfg.ClientAPI.RecaptchaPublicKey = "pub"
base.Cfg.ClientAPI.RecaptchaPrivateKey = "priv" base.Cfg.ClientAPI.RecaptchaPrivateKey = "priv"
@ -33,7 +33,7 @@ func Test_AuthFallback(t *testing.T) {
base.Cfg.ClientAPI.RecaptchaSitekeyClass = "h-captcha" base.Cfg.ClientAPI.RecaptchaSitekeyClass = "h-captcha"
} }
cfgErrs := &config.ConfigErrors{} cfgErrs := &config.ConfigErrors{}
base.Cfg.ClientAPI.Verify(cfgErrs, true) base.Cfg.ClientAPI.Verify(cfgErrs)
if len(*cfgErrs) > 0 { if len(*cfgErrs) > 0 {
t.Fatalf("(hCaptcha=%v) unexpected config errors: %s", useHCaptcha, cfgErrs.Error()) t.Fatalf("(hCaptcha=%v) unexpected config errors: %s", useHCaptcha, cfgErrs.Error())
} }

View file

@ -18,7 +18,6 @@ import (
"net/http" "net/http"
"github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/internal/httputil"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/util" "github.com/matrix-org/util"
@ -45,15 +44,6 @@ func LeaveRoomByID(
JSON: jsonerror.LeaveServerNoticeError(), JSON: jsonerror.LeaveServerNoticeError(),
} }
} }
switch e := err.(type) {
case httputil.InternalAPIError:
if e.Message == jsonerror.LeaveServerNoticeError().Error() {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: jsonerror.LeaveServerNoticeError(),
}
}
}
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: jsonerror.Unknown(err.Error()), JSON: jsonerror.Unknown(err.Error()),

View file

@ -31,8 +31,6 @@ import (
"time" "time"
"github.com/matrix-org/dendrite/internal" "github.com/matrix-org/dendrite/internal"
internalHTTPUtil "github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/internal/sqlutil"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"github.com/matrix-org/dendrite/internal/eventutil" "github.com/matrix-org/dendrite/internal/eventutil"
@ -861,16 +859,6 @@ func completeRegistration(
JSON: jsonerror.UserInUse("Desired user ID is already taken."), JSON: jsonerror.UserInUse("Desired user ID is already taken."),
} }
} }
switch e := err.(type) {
case internalHTTPUtil.InternalAPIError:
conflictErr := &userapi.ErrorConflict{Message: sqlutil.ErrUserExists.Error()}
if e.Message == conflictErr.Error() {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.UserInUse("Desired user ID is already taken."),
}
}
}
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusInternalServerError, Code: http.StatusInternalServerError,
JSON: jsonerror.Unknown("failed to create account: " + err.Error()), JSON: jsonerror.Unknown("failed to create account: " + err.Error()),

View file

@ -201,8 +201,8 @@ func TestValidationOfApplicationServices(t *testing.T) {
// Set up a config // Set up a config
fakeConfig := &config.Dendrite{} fakeConfig := &config.Dendrite{}
fakeConfig.Defaults(config.DefaultOpts{ fakeConfig.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: true,
}) })
fakeConfig.Global.ServerName = "localhost" fakeConfig.Global.ServerName = "localhost"
fakeConfig.ClientAPI.Derived.ApplicationServices = []config.ApplicationService{fakeApplicationService} fakeConfig.ClientAPI.Derived.ApplicationServices = []config.ApplicationService{fakeApplicationService}

View file

@ -80,8 +80,8 @@ type P2PMonolith struct {
func GenerateDefaultConfig(sk ed25519.PrivateKey, storageDir string, cacheDir string, dbPrefix string) *config.Dendrite { func GenerateDefaultConfig(sk ed25519.PrivateKey, storageDir string, cacheDir string, dbPrefix string) *config.Dendrite {
cfg := config.Dendrite{} cfg := config.Dendrite{}
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: true,
}) })
cfg.Global.PrivateKey = sk cfg.Global.PrivateKey = sk
cfg.Global.JetStream.StoragePath = config.Path(fmt.Sprintf("%s/", filepath.Join(cacheDir, dbPrefix))) cfg.Global.JetStream.StoragePath = config.Path(fmt.Sprintf("%s/", filepath.Join(cacheDir, dbPrefix)))
@ -121,9 +121,9 @@ func (p *P2PMonolith) SetupPinecone(sk ed25519.PrivateKey) {
func (p *P2PMonolith) SetupDendrite(cfg *config.Dendrite, port int, enableRelaying bool, enableMetrics bool, enableWebsockets bool) { func (p *P2PMonolith) SetupDendrite(cfg *config.Dendrite, port int, enableRelaying bool, enableMetrics bool, enableWebsockets bool) {
if enableMetrics { if enableMetrics {
p.BaseDendrite = base.NewBaseDendrite(cfg, "Monolith") p.BaseDendrite = base.NewBaseDendrite(cfg)
} else { } else {
p.BaseDendrite = base.NewBaseDendrite(cfg, "Monolith", base.DisableMetrics) p.BaseDendrite = base.NewBaseDendrite(cfg, base.DisableMetrics)
} }
p.port = port p.port = port
p.BaseDendrite.ConfigureAdminEndpoints() p.BaseDendrite.ConfigureAdminEndpoints()
@ -236,7 +236,6 @@ func (p *P2PMonolith) Addr() string {
func (p *P2PMonolith) setupHttpServers(userProvider *users.PineconeUserProvider, enableWebsockets bool) { func (p *P2PMonolith) setupHttpServers(userProvider *users.PineconeUserProvider, enableWebsockets bool) {
p.httpMux = mux.NewRouter().SkipClean(true).UseEncodedPath() p.httpMux = mux.NewRouter().SkipClean(true).UseEncodedPath()
p.httpMux.PathPrefix(httputil.InternalPathPrefix).Handler(p.BaseDendrite.InternalAPIMux)
p.httpMux.PathPrefix(httputil.PublicClientPathPrefix).Handler(p.BaseDendrite.PublicClientAPIMux) p.httpMux.PathPrefix(httputil.PublicClientPathPrefix).Handler(p.BaseDendrite.PublicClientAPIMux)
p.httpMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(p.BaseDendrite.PublicMediaAPIMux) p.httpMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(p.BaseDendrite.PublicMediaAPIMux)
p.httpMux.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(p.BaseDendrite.DendriteAdminMux) p.httpMux.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(p.BaseDendrite.DendriteAdminMux)

View file

@ -117,8 +117,8 @@ func main() {
cfg = setup.ParseFlags(true) cfg = setup.ParseFlags(true)
} else { } else {
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: true,
}) })
cfg.Global.PrivateKey = sk cfg.Global.PrivateKey = sk
cfg.Global.JetStream.StoragePath = config.Path(filepath.Join(*instanceDir, *instanceName)) cfg.Global.JetStream.StoragePath = config.Path(filepath.Join(*instanceDir, *instanceName))
@ -143,7 +143,7 @@ func main() {
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk)) cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID) cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
base := base.NewBaseDendrite(cfg, "Monolith") base := base.NewBaseDendrite(cfg)
base.ConfigureAdminEndpoints() base.ConfigureAdminEndpoints()
defer base.Close() // nolint: errcheck defer base.Close() // nolint: errcheck
@ -157,13 +157,11 @@ func main() {
serverKeyAPI := &signing.YggdrasilKeys{} serverKeyAPI := &signing.YggdrasilKeys{}
keyRing := serverKeyAPI.KeyRing() keyRing := serverKeyAPI.KeyRing()
rsComponent := roomserver.NewInternalAPI( rsAPI := roomserver.NewInternalAPI(
base, base,
) )
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, federation, rsComponent) keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, federation, rsAPI)
rsAPI := rsComponent
userAPI := userapi.NewInternalAPI(base, &cfg.UserAPI, nil, keyAPI, rsAPI, base.PushGatewayHTTPClient()) userAPI := userapi.NewInternalAPI(base, &cfg.UserAPI, nil, keyAPI, rsAPI, base.PushGatewayHTTPClient())
keyAPI.SetUserAPI(userAPI) keyAPI.SetUserAPI(userAPI)
@ -174,7 +172,7 @@ func main() {
base, federation, rsAPI, base.Caches, keyRing, true, base, federation, rsAPI, base.Caches, keyRing, true,
) )
rsComponent.SetFederationAPI(fsAPI, keyRing) rsAPI.SetFederationAPI(fsAPI, keyRing)
monolith := setup.Monolith{ monolith := setup.Monolith{
Config: base.Cfg, Config: base.Cfg,
@ -197,7 +195,6 @@ func main() {
} }
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath() httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
httpRouter.PathPrefix(httputil.InternalPathPrefix).Handler(base.InternalAPIMux)
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux) httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux) httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux) httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux)

View file

@ -1,178 +0,0 @@
// Copyright 2017 Vector Creations 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.
package main
import (
"flag"
"os"
"github.com/sirupsen/logrus"
"github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/federationapi"
"github.com/matrix-org/dendrite/keyserver"
"github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/setup"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/setup/mscs"
"github.com/matrix-org/dendrite/userapi"
uapi "github.com/matrix-org/dendrite/userapi/api"
)
var (
httpBindAddr = flag.String("http-bind-address", ":8008", "The HTTP listening port for the server")
httpsBindAddr = flag.String("https-bind-address", ":8448", "The HTTPS listening port for the server")
apiBindAddr = flag.String("api-bind-address", "localhost:18008", "The HTTP listening port for the internal HTTP APIs (if -api is enabled)")
certFile = flag.String("tls-cert", "", "The PEM formatted X509 certificate to use for TLS")
keyFile = flag.String("tls-key", "", "The PEM private key to use for TLS")
enableHTTPAPIs = flag.Bool("api", false, "Use HTTP APIs instead of short-circuiting (warning: exposes API endpoints!)")
traceInternal = os.Getenv("DENDRITE_TRACE_INTERNAL") == "1"
)
func main() {
cfg := setup.ParseFlags(true)
httpAddr := config.HTTPAddress("http://" + *httpBindAddr)
httpsAddr := config.HTTPAddress("https://" + *httpsBindAddr)
httpAPIAddr := httpAddr
options := []basepkg.BaseDendriteOptions{}
if *enableHTTPAPIs {
logrus.Warnf("DANGER! The -api option is enabled, exposing internal APIs on %q!", *apiBindAddr)
httpAPIAddr = config.HTTPAddress("http://" + *apiBindAddr)
// If the HTTP APIs are enabled then we need to update the Listen
// statements in the configuration so that we know where to find
// the API endpoints. They'll listen on the same port as the monolith
// itself.
cfg.AppServiceAPI.InternalAPI.Connect = httpAPIAddr
cfg.ClientAPI.InternalAPI.Connect = httpAPIAddr
cfg.FederationAPI.InternalAPI.Connect = httpAPIAddr
cfg.KeyServer.InternalAPI.Connect = httpAPIAddr
cfg.MediaAPI.InternalAPI.Connect = httpAPIAddr
cfg.RoomServer.InternalAPI.Connect = httpAPIAddr
cfg.SyncAPI.InternalAPI.Connect = httpAPIAddr
cfg.UserAPI.InternalAPI.Connect = httpAPIAddr
options = append(options, basepkg.UseHTTPAPIs)
}
base := basepkg.NewBaseDendrite(cfg, "Monolith", options...)
defer base.Close() // nolint: errcheck
federation := base.CreateFederationClient()
rsImpl := roomserver.NewInternalAPI(base)
// call functions directly on the impl unless running in HTTP mode
rsAPI := rsImpl
if base.UseHTTPAPIs {
roomserver.AddInternalRoutes(base.InternalAPIMux, rsImpl, base.EnableMetrics)
rsAPI = base.RoomserverHTTPClient()
}
if traceInternal {
rsAPI = &api.RoomserverInternalAPITrace{
Impl: rsAPI,
}
}
fsAPI := federationapi.NewInternalAPI(
base, federation, rsAPI, base.Caches, nil, false,
)
fsImplAPI := fsAPI
if base.UseHTTPAPIs {
federationapi.AddInternalRoutes(base.InternalAPIMux, fsAPI, base.EnableMetrics)
fsAPI = base.FederationAPIHTTPClient()
}
keyRing := fsAPI.KeyRing()
keyImpl := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, fsAPI, rsAPI)
keyAPI := keyImpl
if base.UseHTTPAPIs {
keyserver.AddInternalRoutes(base.InternalAPIMux, keyAPI, base.EnableMetrics)
keyAPI = base.KeyServerHTTPClient()
}
pgClient := base.PushGatewayHTTPClient()
userImpl := userapi.NewInternalAPI(base, &cfg.UserAPI, cfg.Derived.ApplicationServices, keyAPI, rsAPI, pgClient)
userAPI := userImpl
if base.UseHTTPAPIs {
userapi.AddInternalRoutes(base.InternalAPIMux, userAPI, base.EnableMetrics)
userAPI = base.UserAPIClient()
}
if traceInternal {
userAPI = &uapi.UserInternalAPITrace{
Impl: userAPI,
}
}
// TODO: This should use userAPI, not userImpl, but the appservice setup races with
// the listeners and panics at startup if it tries to create appservice accounts
// before the listeners are up.
asAPI := appservice.NewInternalAPI(base, userImpl, rsAPI)
if base.UseHTTPAPIs {
appservice.AddInternalRoutes(base.InternalAPIMux, asAPI, base.EnableMetrics)
asAPI = base.AppserviceHTTPClient()
}
// The underlying roomserver implementation needs to be able to call the fedsender.
// This is different to rsAPI which can be the http client which doesn't need this
// dependency. Other components also need updating after their dependencies are up.
rsImpl.SetFederationAPI(fsAPI, keyRing)
rsImpl.SetAppserviceAPI(asAPI)
rsImpl.SetUserAPI(userAPI)
keyImpl.SetUserAPI(userAPI)
monolith := setup.Monolith{
Config: base.Cfg,
Client: base.CreateClient(),
FedClient: federation,
KeyRing: keyRing,
AppserviceAPI: asAPI,
// always use the concrete impl here even in -http mode because adding public routes
// must be done on the concrete impl not an HTTP client else fedapi will call itself
FederationAPI: fsImplAPI,
RoomserverAPI: rsAPI,
UserAPI: userAPI,
KeyAPI: keyAPI,
}
monolith.AddAllPublicRoutes(base)
if len(base.Cfg.MSCs.MSCs) > 0 {
if err := mscs.Enable(base, &monolith); err != nil {
logrus.WithError(err).Fatalf("Failed to enable MSCs")
}
}
// Expose the matrix APIs directly rather than putting them under a /api path.
go func() {
base.SetupAndServeHTTP(
httpAPIAddr, // internal API
httpAddr, // external API
nil, nil, // TLS settings
)
}()
// Handle HTTPS if certificate and key are provided
if *certFile != "" && *keyFile != "" {
go func() {
base.SetupAndServeHTTP(
basepkg.NoListener, // internal API
httpsAddr, // external API
certFile, keyFile, // TLS settings
)
}()
}
// We want to block forever to let the HTTP and HTTPS handler serve the APIs
base.WaitForShutdown()
}

View file

@ -1,77 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package main
import (
"flag"
"os"
"strings"
"github.com/matrix-org/dendrite/cmd/dendrite-polylith-multi/personalities"
"github.com/matrix-org/dendrite/setup"
"github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
"github.com/sirupsen/logrus"
)
type entrypoint func(base *base.BaseDendrite, cfg *config.Dendrite)
func main() {
cfg := setup.ParseFlags(false)
component := ""
if flag.NFlag() > 0 {
component = flag.Arg(0) // ./dendrite-polylith-multi --config=... clientapi
} else if len(os.Args) > 1 {
component = os.Args[1] // ./dendrite-polylith-multi clientapi
}
components := map[string]entrypoint{
"appservice": personalities.Appservice,
"clientapi": personalities.ClientAPI,
"federationapi": personalities.FederationAPI,
"keyserver": personalities.KeyServer,
"mediaapi": personalities.MediaAPI,
"roomserver": personalities.RoomServer,
"syncapi": personalities.SyncAPI,
"userapi": personalities.UserAPI,
}
start, ok := components[component]
if !ok {
if component == "" {
logrus.Errorf("No component specified")
logrus.Info("The first argument on the command line must be the name of the component to run")
} else {
logrus.Errorf("Unknown component %q specified", component)
}
var list []string
for c := range components {
list = append(list, c)
}
logrus.Infof("Valid components: %s", strings.Join(list, ", "))
os.Exit(1)
}
logrus.Infof("Starting %q component", component)
base := base.NewBaseDendrite(cfg, component, base.PolylithMode) // TODO
defer base.Close() // nolint: errcheck
go start(base, cfg)
base.WaitForShutdown()
}

View file

@ -1,36 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package personalities
import (
"github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/setup/base"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
)
func Appservice(base *base.BaseDendrite, cfg *config.Dendrite) {
userAPI := base.UserAPIClient()
rsAPI := base.RoomserverHTTPClient()
intAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
appservice.AddInternalRoutes(base.InternalAPIMux, intAPI, base.EnableMetrics)
base.SetupAndServeHTTP(
base.Cfg.AppServiceAPI.InternalAPI.Listen, // internal listener
basepkg.NoListener, // external listener
nil, nil,
)
}

View file

@ -1,44 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package personalities
import (
"github.com/matrix-org/dendrite/clientapi"
"github.com/matrix-org/dendrite/internal/transactions"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
)
func ClientAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
federation := base.CreateFederationClient()
asQuery := base.AppserviceHTTPClient()
rsAPI := base.RoomserverHTTPClient()
fsAPI := base.FederationAPIHTTPClient()
userAPI := base.UserAPIClient()
keyAPI := base.KeyServerHTTPClient()
clientapi.AddPublicRoutes(
base, federation, rsAPI, asQuery,
transactions.New(), fsAPI, userAPI, userAPI,
keyAPI, nil,
)
base.SetupAndServeHTTP(
base.Cfg.ClientAPI.InternalAPI.Listen,
base.Cfg.ClientAPI.ExternalAPI.Listen,
nil, nil,
)
}

View file

@ -1,44 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package personalities
import (
"github.com/matrix-org/dendrite/federationapi"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
)
func FederationAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
userAPI := base.UserAPIClient()
federation := base.CreateFederationClient()
rsAPI := base.RoomserverHTTPClient()
keyAPI := base.KeyServerHTTPClient()
fsAPI := federationapi.NewInternalAPI(base, federation, rsAPI, base.Caches, nil, true)
keyRing := fsAPI.KeyRing()
federationapi.AddPublicRoutes(
base,
userAPI, federation, keyRing,
rsAPI, fsAPI, keyAPI, nil,
)
federationapi.AddInternalRoutes(base.InternalAPIMux, fsAPI, base.EnableMetrics)
base.SetupAndServeHTTP(
base.Cfg.FederationAPI.InternalAPI.Listen,
base.Cfg.FederationAPI.ExternalAPI.Listen,
nil, nil,
)
}

View file

@ -1,36 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package personalities
import (
"github.com/matrix-org/dendrite/keyserver"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
)
func KeyServer(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
fsAPI := base.FederationAPIHTTPClient()
rsAPI := base.RoomserverHTTPClient()
intAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, fsAPI, rsAPI)
intAPI.SetUserAPI(base.UserAPIClient())
keyserver.AddInternalRoutes(base.InternalAPIMux, intAPI, base.EnableMetrics)
base.SetupAndServeHTTP(
base.Cfg.KeyServer.InternalAPI.Listen, // internal listener
basepkg.NoListener, // external listener
nil, nil,
)
}

View file

@ -1,36 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package personalities
import (
"github.com/matrix-org/dendrite/mediaapi"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
)
func MediaAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
userAPI := base.UserAPIClient()
client := base.CreateClient()
mediaapi.AddPublicRoutes(
base, userAPI, client,
)
base.SetupAndServeHTTP(
base.Cfg.MediaAPI.InternalAPI.Listen,
base.Cfg.MediaAPI.ExternalAPI.Listen,
nil, nil,
)
}

View file

@ -1,36 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package personalities
import (
"github.com/matrix-org/dendrite/roomserver"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
)
func RoomServer(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
asAPI := base.AppserviceHTTPClient()
fsAPI := base.FederationAPIHTTPClient()
rsAPI := roomserver.NewInternalAPI(base)
rsAPI.SetFederationAPI(fsAPI, fsAPI.KeyRing())
rsAPI.SetAppserviceAPI(asAPI)
roomserver.AddInternalRoutes(base.InternalAPIMux, rsAPI, base.EnableMetrics)
base.SetupAndServeHTTP(
base.Cfg.RoomServer.InternalAPI.Listen, // internal listener
basepkg.NoListener, // external listener
nil, nil,
)
}

View file

@ -1,39 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package personalities
import (
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/syncapi"
)
func SyncAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
userAPI := base.UserAPIClient()
rsAPI := base.RoomserverHTTPClient()
syncapi.AddPublicRoutes(
base,
userAPI, rsAPI,
base.KeyServerHTTPClient(),
)
base.SetupAndServeHTTP(
base.Cfg.SyncAPI.InternalAPI.Listen,
base.Cfg.SyncAPI.ExternalAPI.Listen,
nil, nil,
)
}

View file

@ -1,37 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package personalities
import (
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/userapi"
)
func UserAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
userAPI := userapi.NewInternalAPI(
base, &cfg.UserAPI, cfg.Derived.ApplicationServices,
base.KeyServerHTTPClient(), base.RoomserverHTTPClient(),
base.PushGatewayHTTPClient(),
)
userapi.AddInternalRoutes(base.InternalAPIMux, userAPI, base.EnableMetrics)
base.SetupAndServeHTTP(
base.Cfg.UserAPI.InternalAPI.Listen, // internal listener
basepkg.NoListener, // external listener
nil, nil,
)
}

View file

@ -45,6 +45,10 @@ var (
const HEAD = "HEAD" const HEAD = "HEAD"
// The binary was renamed after v0.11.1, so everything after that should use the new name
var binaryChangeVersion, _ = semver.NewVersion("v0.11.1")
var latest, _ = semver.NewVersion("v6.6.6") // Dummy version, used as "HEAD"
// Embed the Dockerfile to use when building dendrite versions. // Embed the Dockerfile to use when building dendrite versions.
// We cannot use the dockerfile associated with the repo with each version sadly due to changes in // We cannot use the dockerfile associated with the repo with each version sadly due to changes in
// Docker versions. Specifically, earlier Dendrite versions are incompatible with newer Docker clients // Docker versions. Specifically, earlier Dendrite versions are incompatible with newer Docker clients
@ -54,12 +58,13 @@ const HEAD = "HEAD"
const DockerfilePostgreSQL = `FROM golang:1.18-stretch as build const DockerfilePostgreSQL = `FROM golang:1.18-stretch as build
RUN apt-get update && apt-get install -y postgresql RUN apt-get update && apt-get install -y postgresql
WORKDIR /build WORKDIR /build
ARG BINARY
# Copy the build context to the repo as this is the right dendrite code. This is different to the # Copy the build context to the repo as this is the right dendrite code. This is different to the
# Complement Dockerfile which wgets a branch. # Complement Dockerfile which wgets a branch.
COPY . . COPY . .
RUN go build ./cmd/dendrite-monolith-server RUN go build ./cmd/${BINARY}
RUN go build ./cmd/generate-keys RUN go build ./cmd/generate-keys
RUN go build ./cmd/generate-config RUN go build ./cmd/generate-config
RUN go build ./cmd/create-account RUN go build ./cmd/create-account
@ -88,22 +93,24 @@ done \n\
\n\ \n\
sed -i "s/server_name: localhost/server_name: ${SERVER_NAME}/g" dendrite.yaml \n\ sed -i "s/server_name: localhost/server_name: ${SERVER_NAME}/g" dendrite.yaml \n\
PARAMS="--tls-cert server.crt --tls-key server.key --config dendrite.yaml" \n\ PARAMS="--tls-cert server.crt --tls-key server.key --config dendrite.yaml" \n\
./dendrite-monolith-server --really-enable-open-registration ${PARAMS} || ./dendrite-monolith-server ${PARAMS} \n\ ./${BINARY} --really-enable-open-registration ${PARAMS} || ./${BINARY} ${PARAMS} \n\
' > run_dendrite.sh && chmod +x run_dendrite.sh ' > run_dendrite.sh && chmod +x run_dendrite.sh
ENV SERVER_NAME=localhost ENV SERVER_NAME=localhost
ENV BINARY=dendrite
EXPOSE 8008 8448 EXPOSE 8008 8448
CMD /build/run_dendrite.sh ` CMD /build/run_dendrite.sh`
const DockerfileSQLite = `FROM golang:1.18-stretch as build const DockerfileSQLite = `FROM golang:1.18-stretch as build
RUN apt-get update && apt-get install -y postgresql RUN apt-get update && apt-get install -y postgresql
WORKDIR /build WORKDIR /build
ARG BINARY
# Copy the build context to the repo as this is the right dendrite code. This is different to the # Copy the build context to the repo as this is the right dendrite code. This is different to the
# Complement Dockerfile which wgets a branch. # Complement Dockerfile which wgets a branch.
COPY . . COPY . .
RUN go build ./cmd/dendrite-monolith-server RUN go build ./cmd/${BINARY}
RUN go build ./cmd/generate-keys RUN go build ./cmd/generate-keys
RUN go build ./cmd/generate-config RUN go build ./cmd/generate-config
RUN go build ./cmd/create-account RUN go build ./cmd/create-account
@ -118,10 +125,11 @@ RUN sed -i "s%connection_string:.file:%connection_string: file:\/var\/lib\/postg
RUN echo '\ RUN echo '\
sed -i "s/server_name: localhost/server_name: ${SERVER_NAME}/g" dendrite.yaml \n\ sed -i "s/server_name: localhost/server_name: ${SERVER_NAME}/g" dendrite.yaml \n\
PARAMS="--tls-cert server.crt --tls-key server.key --config dendrite.yaml" \n\ PARAMS="--tls-cert server.crt --tls-key server.key --config dendrite.yaml" \n\
./dendrite-monolith-server --really-enable-open-registration ${PARAMS} || ./dendrite-monolith-server ${PARAMS} \n\ ./${BINARY} --really-enable-open-registration ${PARAMS} || ./${BINARY} ${PARAMS} \n\
' > run_dendrite.sh && chmod +x run_dendrite.sh ' > run_dendrite.sh && chmod +x run_dendrite.sh
ENV SERVER_NAME=localhost ENV SERVER_NAME=localhost
ENV BINARY=dendrite
EXPOSE 8008 8448 EXPOSE 8008 8448
CMD /build/run_dendrite.sh ` CMD /build/run_dendrite.sh `
@ -182,7 +190,7 @@ func downloadArchive(cli *http.Client, tmpDir, archiveURL string, dockerfile []b
} }
// buildDendrite builds Dendrite on the branchOrTagName given. Returns the image ID or an error // buildDendrite builds Dendrite on the branchOrTagName given. Returns the image ID or an error
func buildDendrite(httpClient *http.Client, dockerClient *client.Client, tmpDir, branchOrTagName string) (string, error) { func buildDendrite(httpClient *http.Client, dockerClient *client.Client, tmpDir string, branchOrTagName, binary string) (string, error) {
var tarball *bytes.Buffer var tarball *bytes.Buffer
var err error var err error
// If a custom HEAD location is given, use that, else pull from github. Mostly useful for CI // If a custom HEAD location is given, use that, else pull from github. Mostly useful for CI
@ -216,6 +224,9 @@ func buildDendrite(httpClient *http.Client, dockerClient *client.Client, tmpDir,
log.Printf("%s: Building version %s\n", branchOrTagName, branchOrTagName) log.Printf("%s: Building version %s\n", branchOrTagName, branchOrTagName)
res, err := dockerClient.ImageBuild(context.Background(), tarball, types.ImageBuildOptions{ res, err := dockerClient.ImageBuild(context.Background(), tarball, types.ImageBuildOptions{
Tags: []string{"dendrite-upgrade"}, Tags: []string{"dendrite-upgrade"},
BuildArgs: map[string]*string{
"BINARY": &binary,
},
}) })
if err != nil { if err != nil {
return "", fmt.Errorf("failed to start building image: %s", err) return "", fmt.Errorf("failed to start building image: %s", err)
@ -272,7 +283,7 @@ func getAndSortVersionsFromGithub(httpClient *http.Client) (semVers []*semver.Ve
return semVers, nil return semVers, nil
} }
func calculateVersions(cli *http.Client, from, to string, direct bool) []string { func calculateVersions(cli *http.Client, from, to string, direct bool) []*semver.Version {
semvers, err := getAndSortVersionsFromGithub(cli) semvers, err := getAndSortVersionsFromGithub(cli)
if err != nil { if err != nil {
log.Fatalf("failed to collect semvers from github: %s", err) log.Fatalf("failed to collect semvers from github: %s", err)
@ -320,28 +331,25 @@ func calculateVersions(cli *http.Client, from, to string, direct bool) []string
} }
semvers = semvers[:i+1] semvers = semvers[:i+1]
} }
var versions []string
for _, sv := range semvers {
versions = append(versions, sv.Original())
}
if to == HEAD { if to == HEAD {
versions = append(versions, HEAD) semvers = append(semvers, latest)
} }
if direct { if direct {
versions = []string{versions[0], versions[len(versions)-1]} semvers = []*semver.Version{semvers[0], semvers[len(semvers)-1]}
} }
return versions return semvers
} }
func buildDendriteImages(httpClient *http.Client, dockerClient *client.Client, baseTempDir string, concurrency int, branchOrTagNames []string) map[string]string { func buildDendriteImages(httpClient *http.Client, dockerClient *client.Client, baseTempDir string, concurrency int, versions []*semver.Version) map[string]string {
// concurrently build all versions, this can be done in any order. The mutex protects the map // concurrently build all versions, this can be done in any order. The mutex protects the map
branchToImageID := make(map[string]string) branchToImageID := make(map[string]string)
var mu sync.Mutex var mu sync.Mutex
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(concurrency) wg.Add(concurrency)
ch := make(chan string, len(branchOrTagNames)) ch := make(chan *semver.Version, len(versions))
for _, branchName := range branchOrTagNames { for _, branchName := range versions {
ch <- branchName ch <- branchName
} }
close(ch) close(ch)
@ -349,11 +357,13 @@ func buildDendriteImages(httpClient *http.Client, dockerClient *client.Client, b
for i := 0; i < concurrency; i++ { for i := 0; i < concurrency; i++ {
go func() { go func() {
defer wg.Done() defer wg.Done()
for branchName := range ch { for version := range ch {
branchName, binary := versionToBranchAndBinary(version)
log.Printf("Building version %s with binary %s", branchName, binary)
tmpDir := baseTempDir + alphaNumerics.ReplaceAllString(branchName, "") tmpDir := baseTempDir + alphaNumerics.ReplaceAllString(branchName, "")
imgID, err := buildDendrite(httpClient, dockerClient, tmpDir, branchName) imgID, err := buildDendrite(httpClient, dockerClient, tmpDir, branchName, binary)
if err != nil { if err != nil {
log.Fatalf("%s: failed to build dendrite image: %s", branchName, err) log.Fatalf("%s: failed to build dendrite image: %s", version, err)
} }
mu.Lock() mu.Lock()
branchToImageID[branchName] = imgID branchToImageID[branchName] = imgID
@ -365,13 +375,14 @@ func buildDendriteImages(httpClient *http.Client, dockerClient *client.Client, b
return branchToImageID return branchToImageID
} }
func runImage(dockerClient *client.Client, volumeName, version, imageID string) (csAPIURL, containerID string, err error) { func runImage(dockerClient *client.Client, volumeName string, branchNameToImageID map[string]string, version *semver.Version) (csAPIURL, containerID string, err error) {
log.Printf("%s: running image %s\n", version, imageID) branchName, binary := versionToBranchAndBinary(version)
imageID := branchNameToImageID[branchName]
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancel() defer cancel()
body, err := dockerClient.ContainerCreate(ctx, &container.Config{ body, err := dockerClient.ContainerCreate(ctx, &container.Config{
Image: imageID, Image: imageID,
Env: []string{"SERVER_NAME=hs1"}, Env: []string{"SERVER_NAME=hs1", fmt.Sprintf("BINARY=%s", binary)},
Labels: map[string]string{ Labels: map[string]string{
dendriteUpgradeTestLabel: "yes", dendriteUpgradeTestLabel: "yes",
}, },
@ -384,7 +395,7 @@ func runImage(dockerClient *client.Client, volumeName, version, imageID string)
Target: "/var/lib/postgresql/9.6/main", Target: "/var/lib/postgresql/9.6/main",
}, },
}, },
}, nil, nil, "dendrite_upgrade_test_"+version) }, nil, nil, "dendrite_upgrade_test_"+branchName)
if err != nil { if err != nil {
return "", "", fmt.Errorf("failed to ContainerCreate: %s", err) return "", "", fmt.Errorf("failed to ContainerCreate: %s", err)
} }
@ -451,8 +462,8 @@ func destroyContainer(dockerClient *client.Client, containerID string) {
} }
} }
func loadAndRunTests(dockerClient *client.Client, volumeName, v string, branchToImageID map[string]string) error { func loadAndRunTests(dockerClient *client.Client, volumeName string, v *semver.Version, branchToImageID map[string]string) error {
csAPIURL, containerID, err := runImage(dockerClient, volumeName, v, branchToImageID[v]) csAPIURL, containerID, err := runImage(dockerClient, volumeName, branchToImageID, v)
if err != nil { if err != nil {
return fmt.Errorf("failed to run container for branch %v: %v", v, err) return fmt.Errorf("failed to run container for branch %v: %v", v, err)
} }
@ -470,9 +481,10 @@ func loadAndRunTests(dockerClient *client.Client, volumeName, v string, branchTo
} }
// test that create-account is working // test that create-account is working
func testCreateAccount(dockerClient *client.Client, v string, containerID string) error { func testCreateAccount(dockerClient *client.Client, version *semver.Version, containerID string) error {
createUser := strings.ToLower("createaccountuser-" + v) branchName, _ := versionToBranchAndBinary(version)
log.Printf("%s: Creating account %s with create-account\n", v, createUser) createUser := strings.ToLower("createaccountuser-" + branchName)
log.Printf("%s: Creating account %s with create-account\n", branchName, createUser)
respID, err := dockerClient.ContainerExecCreate(context.Background(), containerID, types.ExecConfig{ respID, err := dockerClient.ContainerExecCreate(context.Background(), containerID, types.ExecConfig{
AttachStderr: true, AttachStderr: true,
@ -504,9 +516,21 @@ func testCreateAccount(dockerClient *client.Client, v string, containerID string
return nil return nil
} }
func verifyTests(dockerClient *client.Client, volumeName string, versions []string, branchToImageID map[string]string) error { func versionToBranchAndBinary(version *semver.Version) (branchName, binary string) {
binary = "dendrite-monolith-server"
branchName = version.Original()
if version.GreaterThan(binaryChangeVersion) {
binary = "dendrite"
if version.Equal(latest) {
branchName = HEAD
}
}
return
}
func verifyTests(dockerClient *client.Client, volumeName string, versions []*semver.Version, branchToImageID map[string]string) error {
lastVer := versions[len(versions)-1] lastVer := versions[len(versions)-1]
csAPIURL, containerID, err := runImage(dockerClient, volumeName, lastVer, branchToImageID[lastVer]) csAPIURL, containerID, err := runImage(dockerClient, volumeName, branchToImageID, lastVer)
if err != nil { if err != nil {
return fmt.Errorf("failed to run container for branch %v: %v", lastVer, err) return fmt.Errorf("failed to run container for branch %v: %v", lastVer, err)
} }

View file

@ -6,6 +6,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/Masterminds/semver/v3"
"github.com/matrix-org/gomatrix" "github.com/matrix-org/gomatrix"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
) )
@ -22,7 +23,8 @@ type user struct {
// - register alice and bob with branch name muxed into the localpart // - register alice and bob with branch name muxed into the localpart
// - create a DM room for the 2 users and exchange messages // - create a DM room for the 2 users and exchange messages
// - create/join a public #global room and exchange messages // - create/join a public #global room and exchange messages
func runTests(baseURL, branchName string) error { func runTests(baseURL string, v *semver.Version) error {
branchName, _ := versionToBranchAndBinary(v)
// register 2 users // register 2 users
users := []user{ users := []user{
{ {
@ -164,15 +166,16 @@ func runTests(baseURL, branchName string) error {
} }
// verifyTestsRan checks that the HS has the right rooms/messages // verifyTestsRan checks that the HS has the right rooms/messages
func verifyTestsRan(baseURL string, branchNames []string) error { func verifyTestsRan(baseURL string, versions []*semver.Version) error {
log.Println("Verifying tests....") log.Println("Verifying tests....")
// check we can login as all users // check we can login as all users
var resp *gomatrix.RespLogin var resp *gomatrix.RespLogin
for _, branchName := range branchNames { for _, version := range versions {
client, err := gomatrix.NewClient(baseURL, "", "") client, err := gomatrix.NewClient(baseURL, "", "")
if err != nil { if err != nil {
return err return err
} }
branchName, _ := versionToBranchAndBinary(version)
userLocalparts := []string{ userLocalparts := []string{
"alice" + branchName, "alice" + branchName,
"bob" + branchName, "bob" + branchName,
@ -224,7 +227,7 @@ func verifyTestsRan(baseURL string, branchNames []string) error {
msgCount += 1 msgCount += 1
} }
} }
wantMsgCount := len(branchNames) * 4 wantMsgCount := len(versions) * 4
if msgCount != wantMsgCount { if msgCount != wantMsgCount {
return fmt.Errorf("got %d messages in global room, want %d", msgCount, wantMsgCount) return fmt.Errorf("got %d messages in global room, want %d", msgCount, wantMsgCount)
} }

109
cmd/dendrite/main.go Normal file
View file

@ -0,0 +1,109 @@
// Copyright 2017 Vector Creations 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.
package main
import (
"flag"
"github.com/sirupsen/logrus"
"github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/federationapi"
"github.com/matrix-org/dendrite/keyserver"
"github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/dendrite/setup"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/setup/mscs"
"github.com/matrix-org/dendrite/userapi"
)
var (
httpBindAddr = flag.String("http-bind-address", ":8008", "The HTTP listening port for the server")
httpsBindAddr = flag.String("https-bind-address", ":8448", "The HTTPS listening port for the server")
certFile = flag.String("tls-cert", "", "The PEM formatted X509 certificate to use for TLS")
keyFile = flag.String("tls-key", "", "The PEM private key to use for TLS")
)
func main() {
cfg := setup.ParseFlags(true)
httpAddr := config.HTTPAddress("http://" + *httpBindAddr)
httpsAddr := config.HTTPAddress("https://" + *httpsBindAddr)
options := []basepkg.BaseDendriteOptions{}
base := basepkg.NewBaseDendrite(cfg, options...)
defer base.Close() // nolint: errcheck
federation := base.CreateFederationClient()
rsAPI := roomserver.NewInternalAPI(base)
fsAPI := federationapi.NewInternalAPI(
base, federation, rsAPI, base.Caches, nil, false,
)
keyRing := fsAPI.KeyRing()
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, fsAPI, rsAPI)
pgClient := base.PushGatewayHTTPClient()
userAPI := userapi.NewInternalAPI(base, &cfg.UserAPI, cfg.Derived.ApplicationServices, keyAPI, rsAPI, pgClient)
asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
// The underlying roomserver implementation needs to be able to call the fedsender.
// This is different to rsAPI which can be the http client which doesn't need this
// dependency. Other components also need updating after their dependencies are up.
rsAPI.SetFederationAPI(fsAPI, keyRing)
rsAPI.SetAppserviceAPI(asAPI)
rsAPI.SetUserAPI(userAPI)
keyAPI.SetUserAPI(userAPI)
monolith := setup.Monolith{
Config: base.Cfg,
Client: base.CreateClient(),
FedClient: federation,
KeyRing: keyRing,
AppserviceAPI: asAPI,
// always use the concrete impl here even in -http mode because adding public routes
// must be done on the concrete impl not an HTTP client else fedapi will call itself
FederationAPI: fsAPI,
RoomserverAPI: rsAPI,
UserAPI: userAPI,
KeyAPI: keyAPI,
}
monolith.AddAllPublicRoutes(base)
if len(base.Cfg.MSCs.MSCs) > 0 {
if err := mscs.Enable(base, &monolith); err != nil {
logrus.WithError(err).Fatalf("Failed to enable MSCs")
}
}
// Expose the matrix APIs directly rather than putting them under a /api path.
go func() {
base.SetupAndServeHTTP(httpAddr, nil, nil)
}()
// Handle HTTPS if certificate and key are provided
if *certFile != "" && *keyFile != "" {
go func() {
base.SetupAndServeHTTP(httpsAddr, certFile, keyFile)
}()
}
// We want to block forever to let the HTTP and HTTPS handler serve the APIs
base.WaitForShutdown()
}

View file

@ -18,7 +18,6 @@ func main() {
dbURI := flag.String("db", "", "The DB URI to use for all components (PostgreSQL only)") dbURI := flag.String("db", "", "The DB URI to use for all components (PostgreSQL only)")
dirPath := flag.String("dir", "./", "The folder to use for paths (like SQLite databases, media storage)") dirPath := flag.String("dir", "./", "The folder to use for paths (like SQLite databases, media storage)")
normalise := flag.String("normalise", "", "Normalise an existing configuration file by adding new/missing options and defaults") normalise := flag.String("normalise", "", "Normalise an existing configuration file by adding new/missing options and defaults")
polylith := flag.Bool("polylith", false, "Generate a config that makes sense for polylith deployments")
flag.Parse() flag.Parse()
var cfg *config.Dendrite var cfg *config.Dendrite
@ -27,14 +26,14 @@ func main() {
Version: config.Version, Version: config.Version,
} }
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: !*polylith, SingleDatabase: true,
}) })
if *serverName != "" { if *serverName != "" {
cfg.Global.ServerName = gomatrixserverlib.ServerName(*serverName) cfg.Global.ServerName = gomatrixserverlib.ServerName(*serverName)
} }
uri := config.DataSource(*dbURI) uri := config.DataSource(*dbURI)
if *polylith || uri.IsSQLite() || uri == "" { if uri.IsSQLite() || uri == "" {
for name, db := range map[string]*config.DatabaseOptions{ for name, db := range map[string]*config.DatabaseOptions{
"federationapi": &cfg.FederationAPI.Database, "federationapi": &cfg.FederationAPI.Database,
"keyserver": &cfg.KeyServer.Database, "keyserver": &cfg.KeyServer.Database,
@ -43,6 +42,7 @@ func main() {
"roomserver": &cfg.RoomServer.Database, "roomserver": &cfg.RoomServer.Database,
"syncapi": &cfg.SyncAPI.Database, "syncapi": &cfg.SyncAPI.Database,
"userapi": &cfg.UserAPI.AccountDatabase, "userapi": &cfg.UserAPI.AccountDatabase,
"relayapi": &cfg.RelayAPI.Database,
} { } {
if uri == "" { if uri == "" {
path := filepath.Join(*dirPath, fmt.Sprintf("dendrite_%s.db", name)) path := filepath.Join(*dirPath, fmt.Sprintf("dendrite_%s.db", name))
@ -96,7 +96,7 @@ func main() {
} }
} else { } else {
var err error var err error
if cfg, err = config.Load(*normalise, !*polylith); err != nil { if cfg, err = config.Load(*normalise); err != nil {
panic(err) panic(err)
} }
} }

View file

@ -40,7 +40,7 @@ func main() {
Level: "error", Level: "error",
}) })
cfg.ClientAPI.RegistrationDisabled = true cfg.ClientAPI.RegistrationDisabled = true
base := base.NewBaseDendrite(cfg, "ResolveState", base.DisableMetrics) base := base.NewBaseDendrite(cfg, base.DisableMetrics)
args := flag.Args() args := flag.Args()
fmt.Println("Room version", *roomVersion) fmt.Println("Room version", *roomVersion)

View file

@ -1,417 +0,0 @@
# This is the Dendrite configuration file.
#
# The configuration is split up into sections - each Dendrite component has a
# configuration section, in addition to the "global" section which applies to
# all components.
# The version of the configuration file.
version: 2
# Global Matrix configuration. This configuration applies to all components.
global:
# The domain name of this homeserver.
server_name: localhost
# The path to the signing private key file, used to sign requests and events.
# Note that this is NOT the same private key as used for TLS! To generate a
# signing key, use "./bin/generate-keys --private-key matrix_key.pem".
private_key: matrix_key.pem
# The paths and expiry timestamps (as a UNIX timestamp in millisecond precision)
# to old signing keys that were formerly in use on this domain name. These
# keys will not be used for federation request or event signing, but will be
# provided to any other homeserver that asks when trying to verify old events.
old_private_keys:
# If the old private key file is available:
# - private_key: old_matrix_key.pem
# expired_at: 1601024554498
# If only the public key (in base64 format) and key ID are known:
# - public_key: mn59Kxfdq9VziYHSBzI7+EDPDcBS2Xl7jeUdiiQcOnM=
# key_id: ed25519:mykeyid
# expired_at: 1601024554498
# How long a remote server can cache our server signing key before requesting it
# again. Increasing this number will reduce the number of requests made by other
# servers for our key but increases the period that a compromised key will be
# considered valid by other homeservers.
key_validity_period: 168h0m0s
# Configuration for in-memory caches. Caches can often improve performance by
# keeping frequently accessed items (like events, identifiers etc.) in memory
# rather than having to read them from the database.
cache:
# The estimated maximum size for the global cache in bytes, or in terabytes,
# gigabytes, megabytes or kilobytes when the appropriate 'tb', 'gb', 'mb' or
# 'kb' suffix is specified. Note that this is not a hard limit, nor is it a
# memory limit for the entire process. A cache that is too small may ultimately
# provide little or no benefit.
max_size_estimated: 1gb
# The maximum amount of time that a cache entry can live for in memory before
# it will be evicted and/or refreshed from the database. Lower values result in
# easier admission of new cache entries but may also increase database load in
# comparison to higher values, so adjust conservatively. Higher values may make
# it harder for new items to make it into the cache, e.g. if new rooms suddenly
# become popular.
max_age: 1h
# The server name to delegate server-server communications to, with optional port
# e.g. localhost:443
well_known_server_name: ""
# The server name to delegate client-server communications to, with optional port
# e.g. localhost:443
well_known_client_name: ""
# Lists of domains that the server will trust as identity servers to verify third
# party identifiers such as phone numbers and email addresses.
trusted_third_party_id_servers:
- matrix.org
- vector.im
# Disables federation. Dendrite will not be able to communicate with other servers
# in the Matrix federation and the federation API will not be exposed.
disable_federation: false
# Configures the handling of presence events. Inbound controls whether we receive
# presence events from other servers, outbound controls whether we send presence
# events for our local users to other servers.
presence:
enable_inbound: false
enable_outbound: false
# Configures phone-home statistics reporting. These statistics contain the server
# name, number of active users and some information on your deployment config.
# We use this information to understand how Dendrite is being used in the wild.
report_stats:
enabled: false
endpoint: https://matrix.org/report-usage-stats/push
# Server notices allows server admins to send messages to all users on the server.
server_notices:
enabled: false
# The local part, display name and avatar URL (as a mxc:// URL) for the user that
# will send the server notices. These are visible to all users on the deployment.
local_part: "_server"
display_name: "Server Alerts"
avatar_url: ""
# The room name to be used when sending server notices. This room name will
# appear in user clients.
room_name: "Server Alerts"
# Configuration for NATS JetStream
jetstream:
# A list of NATS Server addresses to connect to. If none are specified, an
# internal NATS server will be started automatically when running Dendrite in
# monolith mode. For polylith deployments, it is required to specify the address
# of at least one NATS Server node.
addresses:
- hostname:4222
# Disable the validation of TLS certificates of NATS. This is
# not recommended in production since it may allow NATS traffic
# to be sent to an insecure endpoint.
disable_tls_validation: false
# The prefix to use for stream names for this homeserver - really only useful
# if you are running more than one Dendrite server on the same NATS deployment.
topic_prefix: Dendrite
# Configuration for Prometheus metric collection.
metrics:
enabled: false
basic_auth:
username: metrics
password: metrics
# Optional DNS cache. The DNS cache may reduce the load on DNS servers if there
# is no local caching resolver available for use.
dns_cache:
enabled: false
cache_size: 256
cache_lifetime: "5m" # 5 minutes; https://pkg.go.dev/time@master#ParseDuration
# Configuration for the Appservice API.
app_service_api:
internal_api:
listen: http://[::]:7777 # The listen address for incoming API requests
connect: http://app_service_api:7777 # The connect address for other components to use
# Disable the validation of TLS certificates of appservices. This is
# not recommended in production since it may allow appservice traffic
# to be sent to an insecure endpoint.
disable_tls_validation: false
# Appservice configuration files to load into this homeserver.
config_files:
# - /path/to/appservice_registration.yaml
# Configuration for the Client API.
client_api:
internal_api:
listen: http://[::]:7771 # The listen address for incoming API requests
connect: http://client_api:7771 # The connect address for other components to use
external_api:
listen: http://[::]:8071
# Prevents new users from being able to register on this homeserver, except when
# using the registration shared secret below.
registration_disabled: true
# Prevents new guest accounts from being created. Guest registration is also
# disabled implicitly by setting 'registration_disabled' above.
guests_disabled: true
# If set, allows registration by anyone who knows the shared secret, regardless
# of whether registration is otherwise disabled.
registration_shared_secret: ""
# Whether to require reCAPTCHA for registration. If you have enabled registration
# then this is HIGHLY RECOMMENDED to reduce the risk of your homeserver being used
# for coordinated spam attacks.
enable_registration_captcha: false
# Settings for ReCAPTCHA.
recaptcha_public_key: ""
recaptcha_private_key: ""
recaptcha_bypass_secret: ""
# To use hcaptcha.com instead of ReCAPTCHA, set the following parameters, otherwise just keep them empty.
# recaptcha_siteverify_api: "https://hcaptcha.com/siteverify"
# recaptcha_api_js_url: "https://js.hcaptcha.com/1/api.js"
# recaptcha_form_field: "h-captcha-response"
# recaptcha_sitekey_class: "h-captcha"
# TURN server information that this homeserver should send to clients.
turn:
turn_user_lifetime: "5m"
turn_uris:
# - turn:turn.server.org?transport=udp
# - turn:turn.server.org?transport=tcp
turn_shared_secret: ""
# If your TURN server requires static credentials, then you will need to enter
# them here instead of supplying a shared secret. Note that these credentials
# will be visible to clients!
# turn_username: ""
# turn_password: ""
# Settings for rate-limited endpoints. Rate limiting kicks in after the threshold
# number of "slots" have been taken by requests from a specific host. Each "slot"
# will be released after the cooloff time in milliseconds. Server administrators
# and appservice users are exempt from rate limiting by default.
rate_limiting:
enabled: true
threshold: 20
cooloff_ms: 500
exempt_user_ids:
# - "@user:domain.com"
# Configuration for the Federation API.
federation_api:
internal_api:
listen: http://[::]:7772 # The listen address for incoming API requests
connect: http://federation_api:7772 # The connect address for other components to use
external_api:
listen: http://[::]:8072
database:
connection_string: postgresql://username:password@hostname/dendrite_federationapi?sslmode=disable
max_open_conns: 10
max_idle_conns: 2
conn_max_lifetime: -1
# How many times we will try to resend a failed transaction to a specific server. The
# backoff is 2**x seconds, so 1 = 2 seconds, 2 = 4 seconds, 3 = 8 seconds etc. Once
# the max retries are exceeded, Dendrite will no longer try to send transactions to
# that server until it comes back to life and connects to us again.
send_max_retries: 16
# Disable the validation of TLS certificates of remote federated homeservers. Do not
# enable this option in production as it presents a security risk!
disable_tls_validation: false
# Disable HTTP keepalives, which also prevents connection reuse. Dendrite will typically
# keep HTTP connections open to remote hosts for 5 minutes as they can be reused much
# more quickly than opening new connections each time. Disabling keepalives will close
# HTTP connections immediately after a successful request but may result in more CPU and
# memory being used on TLS handshakes for each new connection instead.
disable_http_keepalives: false
# Perspective keyservers to use as a backup when direct key fetches fail. This may
# be required to satisfy key requests for servers that are no longer online when
# joining some rooms.
key_perspectives:
- server_name: matrix.org
keys:
- key_id: ed25519:auto
public_key: Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw
- key_id: ed25519:a_RXGa
public_key: l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ
# This option will control whether Dendrite will prefer to look up keys directly
# or whether it should try perspective servers first, using direct fetches as a
# last resort.
prefer_direct_fetch: false
# Configuration for the Key Server (for end-to-end encryption).
key_server:
internal_api:
listen: http://[::]:7779 # The listen address for incoming API requests
connect: http://key_server:7779 # The connect address for other components to use
database:
connection_string: postgresql://username:password@hostname/dendrite_keyserver?sslmode=disable
max_open_conns: 10
max_idle_conns: 2
conn_max_lifetime: -1
# Configuration for the Media API.
media_api:
internal_api:
listen: http://[::]:7774 # The listen address for incoming API requests
connect: http://media_api:7774 # The connect address for other components to use
external_api:
listen: http://[::]:8074
database:
connection_string: postgresql://username:password@hostname/dendrite_mediaapi?sslmode=disable
max_open_conns: 5
max_idle_conns: 2
conn_max_lifetime: -1
# Storage path for uploaded media. May be relative or absolute.
base_path: ./media_store
# The maximum allowed file size (in bytes) for media uploads to this homeserver
# (0 = unlimited). If using a reverse proxy, ensure it allows requests at least
#this large (e.g. the client_max_body_size setting in nginx).
max_file_size_bytes: 10485760
# Whether to dynamically generate thumbnails if needed.
dynamic_thumbnails: false
# The maximum number of simultaneous thumbnail generators to run.
max_thumbnail_generators: 10
# A list of thumbnail sizes to be generated for media content.
thumbnail_sizes:
- width: 32
height: 32
method: crop
- width: 96
height: 96
method: crop
- width: 640
height: 480
method: scale
# Configuration for enabling experimental MSCs on this homeserver.
mscs:
mscs:
# - msc2836 # (Threading, see https://github.com/matrix-org/matrix-doc/pull/2836)
# - msc2946 # (Spaces Summary, see https://github.com/matrix-org/matrix-doc/pull/2946)
database:
connection_string: postgresql://username:password@hostname/dendrite_mscs?sslmode=disable
max_open_conns: 5
max_idle_conns: 2
conn_max_lifetime: -1
# Configuration for the Room Server.
room_server:
internal_api:
listen: http://[::]:7770 # The listen address for incoming API requests
connect: http://room_server:7770 # The connect address for other components to use
database:
connection_string: postgresql://username:password@hostname/dendrite_roomserver?sslmode=disable
max_open_conns: 10
max_idle_conns: 2
conn_max_lifetime: -1
# Configuration for the Sync API.
sync_api:
internal_api:
listen: http://[::]:7773 # The listen address for incoming API requests
connect: http://sync_api:7773 # The connect address for other components to use
external_api:
listen: http://[::]:8073
database:
connection_string: postgresql://username:password@hostname/dendrite_syncapi?sslmode=disable
max_open_conns: 10
max_idle_conns: 2
conn_max_lifetime: -1
# Configuration for the full-text search engine.
search:
# Whether or not search is enabled.
enabled: false
# The path where the search index will be created in.
index_path: "./searchindex"
# The language most likely to be used on the server - used when indexing, to
# ensure the returned results match expectations. A full list of possible languages
# can be found at https://github.com/blevesearch/bleve/tree/master/analysis/lang
language: "en"
# This option controls which HTTP header to inspect to find the real remote IP
# address of the client. This is likely required if Dendrite is running behind
# a reverse proxy server.
# real_ip_header: X-Real-IP
# Configuration for the User API.
user_api:
internal_api:
listen: http://[::]:7781 # The listen address for incoming API requests
connect: http://user_api:7781 # The connect address for other components to use
account_database:
connection_string: postgresql://username:password@hostname/dendrite_userapi?sslmode=disable
max_open_conns: 10
max_idle_conns: 2
conn_max_lifetime: -1
# The cost when hashing passwords on registration/login. Default: 10. Min: 4, Max: 31
# See https://pkg.go.dev/golang.org/x/crypto/bcrypt for more information.
# Setting this lower makes registration/login consume less CPU resources at the cost
# of security should the database be compromised. Setting this higher makes registration/login
# consume more CPU resources but makes it harder to brute force password hashes. This value
# can be lowered if performing tests or on embedded Dendrite instances (e.g WASM builds).
bcrypt_cost: 10
# The length of time that a token issued for a relying party from
# /_matrix/client/r0/user/{userId}/openid/request_token endpoint
# is considered to be valid in milliseconds.
# The default lifetime is 3600000ms (60 minutes).
# openid_token_lifetime_ms: 3600000
# Users who register on this homeserver will automatically be joined to the rooms listed under "auto_join_rooms" option.
# By default, any room aliases included in this list will be created as a publicly joinable room
# when the first user registers for the homeserver. If the room already exists,
# make certain it is a publicly joinable room, i.e. the join rule of the room must be set to 'public'.
# As Spaces are just rooms under the hood, Space aliases may also be used.
auto_join_rooms:
# - "#main:matrix.org"
# Configuration for Opentracing.
# See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on
# how this works and how to set it up.
tracing:
enabled: false
jaeger:
serviceName: ""
disabled: false
rpc_metrics: false
tags: []
sampler: null
reporter: null
headers: null
baggage_restrictions: null
throttler: null
# Logging configuration. The "std" logging type controls the logs being sent to
# stdout. The "file" logging type controls logs being written to a log folder on
# the disk. Supported log levels are "debug", "info", "warn", "error".
logging:
- type: std
level: info
- type: file
level: info
params:
path: ./logs

View file

@ -38,7 +38,7 @@ global:
# Global database connection pool, for PostgreSQL monolith deployments only. If # Global database connection pool, for PostgreSQL monolith deployments only. If
# this section is populated then you can omit the "database" blocks in all other # this section is populated then you can omit the "database" blocks in all other
# sections. For polylith deployments, or monolith deployments using SQLite databases, # sections. For monolith deployments using SQLite databases,
# you must configure the "database" block for each component instead. # you must configure the "database" block for each component instead.
database: database:
connection_string: postgresql://username:password@hostname/dendrite?sslmode=disable connection_string: postgresql://username:password@hostname/dendrite?sslmode=disable
@ -113,8 +113,7 @@ global:
jetstream: jetstream:
# A list of NATS Server addresses to connect to. If none are specified, an # A list of NATS Server addresses to connect to. If none are specified, an
# internal NATS server will be started automatically when running Dendrite in # internal NATS server will be started automatically when running Dendrite in
# monolith mode. For polylith deployments, it is required to specify the address # monolith mode.
# of at least one NATS Server node.
addresses: addresses:
# - localhost:4222 # - localhost:4222

View file

@ -35,11 +35,6 @@ possible to migrate an existing Synapse deployment to Dendrite.
No, Dendrite has a very different database schema to Synapse and the two are not interchangeable. No, Dendrite has a very different database schema to Synapse and the two are not interchangeable.
## Should I run a monolith or a polylith deployment?
Monolith deployments are always preferred where possible, and at this time, are far better tested than polylith deployments are. The only reason to consider a polylith deployment is if you wish to run different Dendrite components on separate physical machines, but this is an advanced configuration which we don't
recommend.
## Can I configure which port Dendrite listens on? ## Can I configure which port Dendrite listens on?
Yes, use the cli flag `-http-bind-address`. Yes, use the cli flag `-http-bind-address`.

View file

@ -9,7 +9,5 @@ or alternatively, in the [installation](installation/) folder:
3. [Preparing database storage](installation/3_database.md) 3. [Preparing database storage](installation/3_database.md)
4. [Generating signing keys](installation/4_signingkey.md) 4. [Generating signing keys](installation/4_signingkey.md)
5. [Installing as a monolith](installation/5_install_monolith.md) 5. [Installing as a monolith](installation/5_install_monolith.md)
6. [Installing as a polylith](installation/6_install_polylith.md) 6. [Populate the configuration](installation/7_configuration.md)
7. [Populate the configuration](installation/7_configuration.md) 7. [Starting the monolith](installation/8_starting_monolith.md)
8. [Starting the monolith](installation/8_starting_monolith.md)
9. [Starting the polylith](installation/9_starting_polylith.md)

View file

@ -57,22 +57,16 @@ github.com/matrix-org/util/unique.go:55: UniqueStrings 100.0%
total: (statements) 53.7% total: (statements) 53.7%
``` ```
The total coverage for this run is the last line at the bottom. However, this value is misleading because Dendrite can run in many different configurations, The total coverage for this run is the last line at the bottom. However, this value is misleading because Dendrite can run in many different configurations,
which will never be tested in a single test run (e.g sqlite or postgres, monolith or polylith). To get a more accurate value, additional processing is required which will never be tested in a single test run (e.g sqlite or postgres). To get a more accurate value, additional processing is required
to remove packages which will never be tested and extension MSCs: to remove packages which will never be tested and extension MSCs:
```bash ```bash
# These commands are all similar but change which package paths are _removed_ from the output. # These commands are all similar but change which package paths are _removed_ from the output.
# For Postgres (monolith) # For Postgres
go tool cover -func=/path/to/server-0/integrationcover.log | grep 'github.com/matrix-org/dendrite' | grep -Ev 'inthttp|sqlite|setup/mscs|api_trace' > coverage.txt go tool cover -func=/path/to/server-0/integrationcover.log | grep 'github.com/matrix-org/dendrite' | grep -Ev 'inthttp|sqlite|setup/mscs|api_trace' > coverage.txt
# For Postgres (polylith) # For SQLite
go tool cover -func=/path/to/server-0/integrationcover.log | grep 'github.com/matrix-org/dendrite' | grep -Ev 'sqlite|setup/mscs|api_trace' > coverage.txt
# For SQLite (monolith)
go tool cover -func=/path/to/server-0/integrationcover.log | grep 'github.com/matrix-org/dendrite' | grep -Ev 'inthttp|postgres|setup/mscs|api_trace' > coverage.txt go tool cover -func=/path/to/server-0/integrationcover.log | grep 'github.com/matrix-org/dendrite' | grep -Ev 'inthttp|postgres|setup/mscs|api_trace' > coverage.txt
# For SQLite (polylith)
go tool cover -func=/path/to/server-0/integrationcover.log | grep 'github.com/matrix-org/dendrite' | grep -Ev 'postgres|setup/mscs|api_trace' > coverage.txt
``` ```
A total value can then be calculated using: A total value can then be calculated using:

View file

@ -46,10 +46,10 @@ tracing:
param: 1 param: 1
``` ```
then run the monolith server with `--api true` to use polylith components which do tracing spans: then run the monolith server:
``` ```
./dendrite-monolith-server --tls-cert server.crt --tls-key server.key --config dendrite.yaml --api true ./dendrite-monolith-server --tls-cert server.crt --tls-key server.key --config dendrite.yaml
``` ```
## Checking traces ## Checking traces

View file

@ -1,73 +0,0 @@
---
title: Starting the polylith
parent: Installation
has_toc: true
nav_order: 10
permalink: /installation/start/polylith
---
# Starting the polylith
Once you have completed all of the preparation and installation steps,
you can start your Dendrite polylith deployment by starting the various components
using the `dendrite-polylith-multi` personalities.
## Start the reverse proxy
Ensure that your reverse proxy is started and is proxying the correct
endpoints to the correct components. Software such as [NGINX](https://www.nginx.com) or
[HAProxy](http://www.haproxy.org) can be used for this purpose. A [sample configuration
for NGINX](https://github.com/matrix-org/dendrite/blob/main/docs/nginx/polylith-sample.conf)
is provided.
## Starting the components
Each component must be started individually:
### Client API
```bash
./dendrite-polylith-multi -config /path/to/dendrite.yaml clientapi
```
### Sync API
```bash
./dendrite-polylith-multi -config /path/to/dendrite.yaml syncapi
```
### Media API
```bash
./dendrite-polylith-multi -config /path/to/dendrite.yaml mediaapi
```
### Federation API
```bash
./dendrite-polylith-multi -config /path/to/dendrite.yaml federationapi
```
### Roomserver
```bash
./dendrite-polylith-multi -config /path/to/dendrite.yaml roomserver
```
### Appservice API
```bash
./dendrite-polylith-multi -config /path/to/dendrite.yaml appservice
```
### User API
```bash
./dendrite-polylith-multi -config /path/to/dendrite.yaml userapi
```
### Key server
```bash
./dendrite-polylith-multi -config /path/to/dendrite.yaml keyserver
```

View file

@ -16,12 +16,6 @@ Users can run Dendrite in one of two modes which dictate how these components ar
server with generally low overhead. This mode dramatically simplifies deployment complexity and offers the server with generally low overhead. This mode dramatically simplifies deployment complexity and offers the
best balance between performance and resource usage for low-to-mid volume deployments. best balance between performance and resource usage for low-to-mid volume deployments.
* **Polylith mode** runs all components in isolated processes. Components communicate through an external NATS
server and HTTP APIs, which incur considerable overhead. While this mode allows for more granular control of
resources dedicated toward individual processes, given the additional communications overhead, it is only
necessary for very large deployments.
Given our current state of development, **we recommend monolith mode** for all deployments.
## Databases ## Databases
@ -85,21 +79,15 @@ If using the PostgreSQL database engine, you should install PostgreSQL 12 or lat
### NATS Server ### NATS Server
Monolith deployments come with a built-in [NATS Server](https://github.com/nats-io/nats-server) and Dendrite comes with a built-in [NATS Server](https://github.com/nats-io/nats-server) and
therefore do not need this to be manually installed. If you are planning a monolith installation, you therefore does not need this to be manually installed. If you are planning a monolith installation, you
do not need to do anything. do not need to do anything.
Polylith deployments, however, currently need a standalone NATS Server installation with JetStream
enabled.
To do so, follow the [NATS Server installation instructions](https://docs.nats.io/running-a-nats-service/introduction/installation) and then [start your NATS deployment](https://docs.nats.io/running-a-nats-service/introduction/running). JetStream must be enabled, either by passing the `-js` flag to `nats-server`,
or by specifying the `store_dir` option in the the `jetstream` configuration.
### Reverse proxy ### Reverse proxy
A reverse proxy such as [Caddy](https://caddyserver.com), [NGINX](https://www.nginx.com) or A reverse proxy such as [Caddy](https://caddyserver.com), [NGINX](https://www.nginx.com) or
[HAProxy](http://www.haproxy.org) is required for polylith deployments and is useful for monolith [HAProxy](http://www.haproxy.org) is useful for deployments. Configuring those is not covered in this documentation, although sample configurations
deployments. Configuring those is not covered in this documentation, although sample configurations
for [Caddy](https://github.com/matrix-org/dendrite/blob/main/docs/caddy) and for [Caddy](https://github.com/matrix-org/dendrite/blob/main/docs/caddy) and
[NGINX](https://github.com/matrix-org/dendrite/blob/main/docs/nginx) are provided. [NGINX](https://github.com/matrix-org/dendrite/blob/main/docs/nginx) are provided.

View file

@ -1,34 +0,0 @@
---
title: Installing as a polylith
parent: Installation
has_toc: true
nav_order: 6
permalink: /installation/install/polylith
---
# Installing as a polylith
You can install the Dendrite polylith binary into `$GOPATH/bin` by using `go install`:
```sh
go install ./cmd/dendrite-polylith-multi
```
Alternatively, you can specify a custom path for the binary to be written to using `go build`:
```sh
go build -o /usr/local/bin/ ./cmd/dendrite-polylith-multi
```
The `dendrite-polylith-multi` binary is a "multi-personality" binary which can run as
any of the components depending on the supplied command line parameters.
## Reverse proxy
Polylith deployments require a reverse proxy in order to ensure that requests are
sent to the correct endpoint. You must ensure that a suitable reverse proxy is installed
and configured.
Sample configurations are provided
for [Caddy](https://github.com/matrix-org/dendrite/blob/main/docs/caddy/polylith/Caddyfile)
and [NGINX](https://github.com/matrix-org/dendrite/blob/main/docs/nginx/polylith-sample.conf).

View file

@ -7,11 +7,10 @@ permalink: /installation/configuration
# Configuring Dendrite # Configuring Dendrite
A YAML configuration file is used to configure Dendrite. Sample configuration files are A YAML configuration file is used to configure Dendrite. A sample configuration file is
present in the top level of the Dendrite repository: present in the top level of the Dendrite repository:
* [`dendrite-sample.monolith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.monolith.yaml) * [`dendrite-sample.monolith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.monolith.yaml)
* [`dendrite-sample.polylith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.polylith.yaml)
You will need to duplicate the sample, calling it `dendrite.yaml` for example, and then You will need to duplicate the sample, calling it `dendrite.yaml` for example, and then
tailor it to your installation. At a minimum, you will need to populate the following tailor it to your installation. At a minimum, you will need to populate the following
@ -46,10 +45,9 @@ global:
## JetStream configuration ## JetStream configuration
Monolith deployments can use the built-in NATS Server rather than running a standalone Monolith deployments can use the built-in NATS Server rather than running a standalone
server. If you are building a polylith deployment, or you want to use a standalone NATS server. If you want to use a standalone NATS Server anyway, you can also configure that too.
Server anyway, you can also configure that too.
### Built-in NATS Server (monolith only) ### Built-in NATS Server
In the `global` section, under the `jetstream` key, ensure that no server addresses are In the `global` section, under the `jetstream` key, ensure that no server addresses are
configured and set a `storage_path` to a persistent folder on the filesystem: configured and set a `storage_path` to a persistent folder on the filesystem:
@ -63,7 +61,7 @@ global:
topic_prefix: Dendrite topic_prefix: Dendrite
``` ```
### Standalone NATS Server (monolith and polylith) ### Standalone NATS Server
To use a standalone NATS Server instance, you will need to configure `addresses` field To use a standalone NATS Server instance, you will need to configure `addresses` field
to point to the port that your NATS Server is listening on: to point to the port that your NATS Server is listening on:
@ -86,7 +84,7 @@ one address in the `addresses` field.
Configuring database connections varies based on the [database configuration](database) Configuring database connections varies based on the [database configuration](database)
that you chose. that you chose.
### Global connection pool (monolith with a single PostgreSQL database only) ### Global connection pool
If you are running a monolith deployment and want to use a single connection pool to a If you are running a monolith deployment and want to use a single connection pool to a
single PostgreSQL database, then you must uncomment and configure the `database` section single PostgreSQL database, then you must uncomment and configure the `database` section
@ -109,7 +107,7 @@ override the `global` database configuration.
### Per-component connections (all other configurations) ### Per-component connections (all other configurations)
If you are building a polylith deployment, are using SQLite databases or separate PostgreSQL If you are are using SQLite databases or separate PostgreSQL
databases per component, then you must instead configure the `database` sections under each databases per component, then you must instead configure the `database` sections under each
of the component blocks ,e.g. under the `app_service_api`, `federation_api`, `key_server`, of the component blocks ,e.g. under the `app_service_api`, `federation_api`, `key_server`,
`media_api`, `mscs`, `room_server`, `sync_api` and `user_api` blocks. `media_api`, `mscs`, `room_server`, `sync_api` and `user_api` blocks.

View file

@ -17,14 +17,12 @@ package federationapi
import ( import (
"time" "time"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/matrix-org/dendrite/federationapi/api" "github.com/matrix-org/dendrite/federationapi/api"
federationAPI "github.com/matrix-org/dendrite/federationapi/api" federationAPI "github.com/matrix-org/dendrite/federationapi/api"
"github.com/matrix-org/dendrite/federationapi/consumers" "github.com/matrix-org/dendrite/federationapi/consumers"
"github.com/matrix-org/dendrite/federationapi/internal" "github.com/matrix-org/dendrite/federationapi/internal"
"github.com/matrix-org/dendrite/federationapi/inthttp"
"github.com/matrix-org/dendrite/federationapi/producers" "github.com/matrix-org/dendrite/federationapi/producers"
"github.com/matrix-org/dendrite/federationapi/queue" "github.com/matrix-org/dendrite/federationapi/queue"
"github.com/matrix-org/dendrite/federationapi/statistics" "github.com/matrix-org/dendrite/federationapi/statistics"
@ -41,12 +39,6 @@ import (
"github.com/matrix-org/dendrite/federationapi/routing" "github.com/matrix-org/dendrite/federationapi/routing"
) )
// AddInternalRoutes registers HTTP handlers for the internal API. Invokes functions
// on the given input API.
func AddInternalRoutes(router *mux.Router, intAPI api.FederationInternalAPI, enableMetrics bool) {
inthttp.AddRoutes(intAPI, router, enableMetrics)
}
// AddPublicRoutes sets up and registers HTTP handlers on the base API muxes for the FederationAPI component. // AddPublicRoutes sets up and registers HTTP handlers on the base API muxes for the FederationAPI component.
func AddPublicRoutes( func AddPublicRoutes(
base *base.BaseDendrite, base *base.BaseDendrite,

View file

@ -77,8 +77,8 @@ func TestMain(m *testing.M) {
// API to work. // API to work.
cfg := &config.Dendrite{} cfg := &config.Dendrite{}
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: false,
}) })
cfg.Global.ServerName = gomatrixserverlib.ServerName(s.name) cfg.Global.ServerName = gomatrixserverlib.ServerName(s.name)
cfg.Global.PrivateKey = testPriv cfg.Global.PrivateKey = testPriv
@ -109,7 +109,7 @@ func TestMain(m *testing.M) {
) )
// Finally, build the server key APIs. // Finally, build the server key APIs.
sbase := base.NewBaseDendrite(cfg, "Monolith", base.DisableMetrics) sbase := base.NewBaseDendrite(cfg, base.DisableMetrics)
s.api = NewInternalAPI(sbase, s.fedclient, nil, s.cache, nil, true) s.api = NewInternalAPI(sbase, s.fedclient, nil, s.cache, nil, true)
} }

View file

@ -266,14 +266,14 @@ func TestRoomsV3URLEscapeDoNot404(t *testing.T) {
_, privKey, _ := ed25519.GenerateKey(nil) _, privKey, _ := ed25519.GenerateKey(nil)
cfg := &config.Dendrite{} cfg := &config.Dendrite{}
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: false,
}) })
cfg.Global.KeyID = gomatrixserverlib.KeyID("ed25519:auto") cfg.Global.KeyID = gomatrixserverlib.KeyID("ed25519:auto")
cfg.Global.ServerName = gomatrixserverlib.ServerName("localhost") cfg.Global.ServerName = gomatrixserverlib.ServerName("localhost")
cfg.Global.PrivateKey = privKey cfg.Global.PrivateKey = privKey
cfg.Global.JetStream.InMemory = true cfg.Global.JetStream.InMemory = true
b := base.NewBaseDendrite(cfg, "Monolith", base.DisableMetrics) b := base.NewBaseDendrite(cfg, base.DisableMetrics)
keyRing := &test.NopJSONVerifier{} keyRing := &test.NopJSONVerifier{}
// TODO: This is pretty fragile, as if anything calls anything on these nils this test will break. // TODO: This is pretty fragile, as if anything calls anything on these nils this test will break.
// Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing. // Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing.

View file

@ -121,8 +121,6 @@ func (r *FederationInternalAPI) PerformJoin(
var httpErr gomatrix.HTTPError var httpErr gomatrix.HTTPError
if ok := errors.As(lastErr, &httpErr); ok { if ok := errors.As(lastErr, &httpErr); ok {
httpErr.Message = string(httpErr.Contents) httpErr.Message = string(httpErr.Contents)
// Clear the wrapped error, else serialising to JSON (in polylith mode) will fail
httpErr.WrappedError = nil
response.LastError = &httpErr response.LastError = &httpErr
} else { } else {
response.LastError = &gomatrix.HTTPError{ response.LastError = &gomatrix.HTTPError{
@ -391,8 +389,6 @@ func (r *FederationInternalAPI) PerformOutboundPeek(
var httpErr gomatrix.HTTPError var httpErr gomatrix.HTTPError
if ok := errors.As(lastErr, &httpErr); ok { if ok := errors.As(lastErr, &httpErr); ok {
httpErr.Message = string(httpErr.Contents) httpErr.Message = string(httpErr.Contents)
// Clear the wrapped error, else serialising to JSON (in polylith mode) will fail
httpErr.WrappedError = nil
response.LastError = &httpErr response.LastError = &httpErr
} else { } else {
response.LastError = &gomatrix.HTTPError{ response.LastError = &gomatrix.HTTPError{

View file

@ -1,548 +0,0 @@
package inthttp
import (
"context"
"errors"
"net/http"
"github.com/matrix-org/dendrite/federationapi/api"
"github.com/matrix-org/dendrite/internal/caching"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/gomatrix"
"github.com/matrix-org/gomatrixserverlib"
)
// HTTP paths for the internal HTTP API
const (
FederationAPIQueryJoinedHostServerNamesInRoomPath = "/federationapi/queryJoinedHostServerNamesInRoom"
FederationAPIQueryServerKeysPath = "/federationapi/queryServerKeys"
FederationAPIPerformDirectoryLookupRequestPath = "/federationapi/performDirectoryLookup"
FederationAPIPerformJoinRequestPath = "/federationapi/performJoinRequest"
FederationAPIPerformLeaveRequestPath = "/federationapi/performLeaveRequest"
FederationAPIPerformInviteRequestPath = "/federationapi/performInviteRequest"
FederationAPIPerformOutboundPeekRequestPath = "/federationapi/performOutboundPeekRequest"
FederationAPIPerformBroadcastEDUPath = "/federationapi/performBroadcastEDU"
FederationAPIPerformWakeupServers = "/federationapi/performWakeupServers"
FederationAPIQueryRelayServers = "/federationapi/queryRelayServers"
FederationAPIAddRelayServers = "/federationapi/addRelayServers"
FederationAPIRemoveRelayServers = "/federationapi/removeRelayServers"
FederationAPIGetUserDevicesPath = "/federationapi/client/getUserDevices"
FederationAPIClaimKeysPath = "/federationapi/client/claimKeys"
FederationAPIQueryKeysPath = "/federationapi/client/queryKeys"
FederationAPIBackfillPath = "/federationapi/client/backfill"
FederationAPILookupStatePath = "/federationapi/client/lookupState"
FederationAPILookupStateIDsPath = "/federationapi/client/lookupStateIDs"
FederationAPILookupMissingEventsPath = "/federationapi/client/lookupMissingEvents"
FederationAPIGetEventPath = "/federationapi/client/getEvent"
FederationAPILookupServerKeysPath = "/federationapi/client/lookupServerKeys"
FederationAPIEventRelationshipsPath = "/federationapi/client/msc2836eventRelationships"
FederationAPISpacesSummaryPath = "/federationapi/client/msc2946spacesSummary"
FederationAPIGetEventAuthPath = "/federationapi/client/getEventAuth"
FederationAPIInputPublicKeyPath = "/federationapi/inputPublicKey"
FederationAPIQueryPublicKeyPath = "/federationapi/queryPublicKey"
)
// NewFederationAPIClient creates a FederationInternalAPI implemented by talking to a HTTP POST API.
// If httpClient is nil an error is returned
func NewFederationAPIClient(federationSenderURL string, httpClient *http.Client, cache caching.ServerKeyCache) (api.FederationInternalAPI, error) {
if httpClient == nil {
return nil, errors.New("NewFederationInternalAPIHTTP: httpClient is <nil>")
}
return &httpFederationInternalAPI{
federationAPIURL: federationSenderURL,
httpClient: httpClient,
cache: cache,
}, nil
}
type httpFederationInternalAPI struct {
federationAPIURL string
httpClient *http.Client
cache caching.ServerKeyCache
}
// Handle an instruction to make_leave & send_leave with a remote server.
func (h *httpFederationInternalAPI) PerformLeave(
ctx context.Context,
request *api.PerformLeaveRequest,
response *api.PerformLeaveResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformLeave", h.federationAPIURL+FederationAPIPerformLeaveRequestPath,
h.httpClient, ctx, request, response,
)
}
// Handle sending an invite to a remote server.
func (h *httpFederationInternalAPI) PerformInvite(
ctx context.Context,
request *api.PerformInviteRequest,
response *api.PerformInviteResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformInvite", h.federationAPIURL+FederationAPIPerformInviteRequestPath,
h.httpClient, ctx, request, response,
)
}
// Handle starting a peek on a remote server.
func (h *httpFederationInternalAPI) PerformOutboundPeek(
ctx context.Context,
request *api.PerformOutboundPeekRequest,
response *api.PerformOutboundPeekResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformOutboundPeek", h.federationAPIURL+FederationAPIPerformOutboundPeekRequestPath,
h.httpClient, ctx, request, response,
)
}
// QueryJoinedHostServerNamesInRoom implements FederationInternalAPI
func (h *httpFederationInternalAPI) QueryJoinedHostServerNamesInRoom(
ctx context.Context,
request *api.QueryJoinedHostServerNamesInRoomRequest,
response *api.QueryJoinedHostServerNamesInRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryJoinedHostServerNamesInRoom", h.federationAPIURL+FederationAPIQueryJoinedHostServerNamesInRoomPath,
h.httpClient, ctx, request, response,
)
}
// Handle an instruction to make_join & send_join with a remote server.
func (h *httpFederationInternalAPI) PerformJoin(
ctx context.Context,
request *api.PerformJoinRequest,
response *api.PerformJoinResponse,
) {
if err := httputil.CallInternalRPCAPI(
"PerformJoinRequest", h.federationAPIURL+FederationAPIPerformJoinRequestPath,
h.httpClient, ctx, request, response,
); err != nil {
response.LastError = &gomatrix.HTTPError{
Message: err.Error(),
Code: 0,
WrappedError: err,
}
}
}
// Handle an instruction to make_join & send_join with a remote server.
func (h *httpFederationInternalAPI) PerformDirectoryLookup(
ctx context.Context,
request *api.PerformDirectoryLookupRequest,
response *api.PerformDirectoryLookupResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformDirectoryLookup", h.federationAPIURL+FederationAPIPerformDirectoryLookupRequestPath,
h.httpClient, ctx, request, response,
)
}
// Handle an instruction to broadcast an EDU to all servers in rooms we are joined to.
func (h *httpFederationInternalAPI) PerformBroadcastEDU(
ctx context.Context,
request *api.PerformBroadcastEDURequest,
response *api.PerformBroadcastEDUResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformBroadcastEDU", h.federationAPIURL+FederationAPIPerformBroadcastEDUPath,
h.httpClient, ctx, request, response,
)
}
// Handle an instruction to remove the respective servers from being blacklisted.
func (h *httpFederationInternalAPI) PerformWakeupServers(
ctx context.Context,
request *api.PerformWakeupServersRequest,
response *api.PerformWakeupServersResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformWakeupServers", h.federationAPIURL+FederationAPIPerformWakeupServers,
h.httpClient, ctx, request, response,
)
}
type getUserDevices struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
UserID string
}
func (h *httpFederationInternalAPI) GetUserDevices(
ctx context.Context, origin, s gomatrixserverlib.ServerName, userID string,
) (gomatrixserverlib.RespUserDevices, error) {
return httputil.CallInternalProxyAPI[getUserDevices, gomatrixserverlib.RespUserDevices, *api.FederationClientError](
"GetUserDevices", h.federationAPIURL+FederationAPIGetUserDevicesPath, h.httpClient,
ctx, &getUserDevices{
S: s,
Origin: origin,
UserID: userID,
},
)
}
type claimKeys struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
OneTimeKeys map[string]map[string]string
}
func (h *httpFederationInternalAPI) ClaimKeys(
ctx context.Context, origin, s gomatrixserverlib.ServerName, oneTimeKeys map[string]map[string]string,
) (gomatrixserverlib.RespClaimKeys, error) {
return httputil.CallInternalProxyAPI[claimKeys, gomatrixserverlib.RespClaimKeys, *api.FederationClientError](
"ClaimKeys", h.federationAPIURL+FederationAPIClaimKeysPath, h.httpClient,
ctx, &claimKeys{
S: s,
Origin: origin,
OneTimeKeys: oneTimeKeys,
},
)
}
type queryKeys struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
Keys map[string][]string
}
func (h *httpFederationInternalAPI) QueryKeys(
ctx context.Context, origin, s gomatrixserverlib.ServerName, keys map[string][]string,
) (gomatrixserverlib.RespQueryKeys, error) {
return httputil.CallInternalProxyAPI[queryKeys, gomatrixserverlib.RespQueryKeys, *api.FederationClientError](
"QueryKeys", h.federationAPIURL+FederationAPIQueryKeysPath, h.httpClient,
ctx, &queryKeys{
S: s,
Origin: origin,
Keys: keys,
},
)
}
type backfill struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
RoomID string
Limit int
EventIDs []string
}
func (h *httpFederationInternalAPI) Backfill(
ctx context.Context, origin, s gomatrixserverlib.ServerName, roomID string, limit int, eventIDs []string,
) (gomatrixserverlib.Transaction, error) {
return httputil.CallInternalProxyAPI[backfill, gomatrixserverlib.Transaction, *api.FederationClientError](
"Backfill", h.federationAPIURL+FederationAPIBackfillPath, h.httpClient,
ctx, &backfill{
S: s,
Origin: origin,
RoomID: roomID,
Limit: limit,
EventIDs: eventIDs,
},
)
}
type lookupState struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
RoomID string
EventID string
RoomVersion gomatrixserverlib.RoomVersion
}
func (h *httpFederationInternalAPI) LookupState(
ctx context.Context, origin, s gomatrixserverlib.ServerName, roomID, eventID string, roomVersion gomatrixserverlib.RoomVersion,
) (gomatrixserverlib.RespState, error) {
return httputil.CallInternalProxyAPI[lookupState, gomatrixserverlib.RespState, *api.FederationClientError](
"LookupState", h.federationAPIURL+FederationAPILookupStatePath, h.httpClient,
ctx, &lookupState{
S: s,
Origin: origin,
RoomID: roomID,
EventID: eventID,
RoomVersion: roomVersion,
},
)
}
type lookupStateIDs struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
RoomID string
EventID string
}
func (h *httpFederationInternalAPI) LookupStateIDs(
ctx context.Context, origin, s gomatrixserverlib.ServerName, roomID, eventID string,
) (gomatrixserverlib.RespStateIDs, error) {
return httputil.CallInternalProxyAPI[lookupStateIDs, gomatrixserverlib.RespStateIDs, *api.FederationClientError](
"LookupStateIDs", h.federationAPIURL+FederationAPILookupStateIDsPath, h.httpClient,
ctx, &lookupStateIDs{
S: s,
Origin: origin,
RoomID: roomID,
EventID: eventID,
},
)
}
type lookupMissingEvents struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
RoomID string
Missing gomatrixserverlib.MissingEvents
RoomVersion gomatrixserverlib.RoomVersion
}
func (h *httpFederationInternalAPI) LookupMissingEvents(
ctx context.Context, origin, s gomatrixserverlib.ServerName, roomID string,
missing gomatrixserverlib.MissingEvents, roomVersion gomatrixserverlib.RoomVersion,
) (res gomatrixserverlib.RespMissingEvents, err error) {
return httputil.CallInternalProxyAPI[lookupMissingEvents, gomatrixserverlib.RespMissingEvents, *api.FederationClientError](
"LookupMissingEvents", h.federationAPIURL+FederationAPILookupMissingEventsPath, h.httpClient,
ctx, &lookupMissingEvents{
S: s,
Origin: origin,
RoomID: roomID,
Missing: missing,
RoomVersion: roomVersion,
},
)
}
type getEvent struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
EventID string
}
func (h *httpFederationInternalAPI) GetEvent(
ctx context.Context, origin, s gomatrixserverlib.ServerName, eventID string,
) (gomatrixserverlib.Transaction, error) {
return httputil.CallInternalProxyAPI[getEvent, gomatrixserverlib.Transaction, *api.FederationClientError](
"GetEvent", h.federationAPIURL+FederationAPIGetEventPath, h.httpClient,
ctx, &getEvent{
S: s,
Origin: origin,
EventID: eventID,
},
)
}
type getEventAuth struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
RoomVersion gomatrixserverlib.RoomVersion
RoomID string
EventID string
}
func (h *httpFederationInternalAPI) GetEventAuth(
ctx context.Context, origin, s gomatrixserverlib.ServerName,
roomVersion gomatrixserverlib.RoomVersion, roomID, eventID string,
) (gomatrixserverlib.RespEventAuth, error) {
return httputil.CallInternalProxyAPI[getEventAuth, gomatrixserverlib.RespEventAuth, *api.FederationClientError](
"GetEventAuth", h.federationAPIURL+FederationAPIGetEventAuthPath, h.httpClient,
ctx, &getEventAuth{
S: s,
Origin: origin,
RoomVersion: roomVersion,
RoomID: roomID,
EventID: eventID,
},
)
}
func (h *httpFederationInternalAPI) QueryServerKeys(
ctx context.Context, req *api.QueryServerKeysRequest, res *api.QueryServerKeysResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryServerKeys", h.federationAPIURL+FederationAPIQueryServerKeysPath,
h.httpClient, ctx, req, res,
)
}
type lookupServerKeys struct {
S gomatrixserverlib.ServerName
KeyRequests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp
}
func (h *httpFederationInternalAPI) LookupServerKeys(
ctx context.Context, s gomatrixserverlib.ServerName, keyRequests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp,
) ([]gomatrixserverlib.ServerKeys, error) {
return httputil.CallInternalProxyAPI[lookupServerKeys, []gomatrixserverlib.ServerKeys, *api.FederationClientError](
"LookupServerKeys", h.federationAPIURL+FederationAPILookupServerKeysPath, h.httpClient,
ctx, &lookupServerKeys{
S: s,
KeyRequests: keyRequests,
},
)
}
type eventRelationships struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
Req gomatrixserverlib.MSC2836EventRelationshipsRequest
RoomVer gomatrixserverlib.RoomVersion
}
func (h *httpFederationInternalAPI) MSC2836EventRelationships(
ctx context.Context, origin, s gomatrixserverlib.ServerName, r gomatrixserverlib.MSC2836EventRelationshipsRequest,
roomVersion gomatrixserverlib.RoomVersion,
) (res gomatrixserverlib.MSC2836EventRelationshipsResponse, err error) {
return httputil.CallInternalProxyAPI[eventRelationships, gomatrixserverlib.MSC2836EventRelationshipsResponse, *api.FederationClientError](
"MSC2836EventRelationships", h.federationAPIURL+FederationAPIEventRelationshipsPath, h.httpClient,
ctx, &eventRelationships{
S: s,
Origin: origin,
Req: r,
RoomVer: roomVersion,
},
)
}
type spacesReq struct {
S gomatrixserverlib.ServerName
Origin gomatrixserverlib.ServerName
SuggestedOnly bool
RoomID string
}
func (h *httpFederationInternalAPI) MSC2946Spaces(
ctx context.Context, origin, dst gomatrixserverlib.ServerName, roomID string, suggestedOnly bool,
) (res gomatrixserverlib.MSC2946SpacesResponse, err error) {
return httputil.CallInternalProxyAPI[spacesReq, gomatrixserverlib.MSC2946SpacesResponse, *api.FederationClientError](
"MSC2836EventRelationships", h.federationAPIURL+FederationAPISpacesSummaryPath, h.httpClient,
ctx, &spacesReq{
S: dst,
Origin: origin,
SuggestedOnly: suggestedOnly,
RoomID: roomID,
},
)
}
func (s *httpFederationInternalAPI) KeyRing() *gomatrixserverlib.KeyRing {
// This is a bit of a cheat - we tell gomatrixserverlib that this API is
// both the key database and the key fetcher. While this does have the
// rather unfortunate effect of preventing gomatrixserverlib from handling
// key fetchers directly, we can at least reimplement this behaviour on
// the other end of the API.
return &gomatrixserverlib.KeyRing{
KeyDatabase: s,
KeyFetchers: []gomatrixserverlib.KeyFetcher{},
}
}
func (s *httpFederationInternalAPI) FetcherName() string {
return "httpServerKeyInternalAPI"
}
func (s *httpFederationInternalAPI) StoreKeys(
_ context.Context,
results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult,
) error {
// Run in a background context - we don't want to stop this work just
// because the caller gives up waiting.
ctx := context.Background()
request := api.InputPublicKeysRequest{
Keys: make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult),
}
response := api.InputPublicKeysResponse{}
for req, res := range results {
request.Keys[req] = res
s.cache.StoreServerKey(req, res)
}
return s.InputPublicKeys(ctx, &request, &response)
}
func (s *httpFederationInternalAPI) FetchKeys(
_ context.Context,
requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp,
) (map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error) {
// Run in a background context - we don't want to stop this work just
// because the caller gives up waiting.
ctx := context.Background()
result := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult)
request := api.QueryPublicKeysRequest{
Requests: make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp),
}
response := api.QueryPublicKeysResponse{
Results: make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult),
}
for req, ts := range requests {
if res, ok := s.cache.GetServerKey(req, ts); ok {
result[req] = res
continue
}
request.Requests[req] = ts
}
err := s.QueryPublicKeys(ctx, &request, &response)
if err != nil {
return nil, err
}
for req, res := range response.Results {
result[req] = res
s.cache.StoreServerKey(req, res)
}
return result, nil
}
func (h *httpFederationInternalAPI) InputPublicKeys(
ctx context.Context,
request *api.InputPublicKeysRequest,
response *api.InputPublicKeysResponse,
) error {
return httputil.CallInternalRPCAPI(
"InputPublicKey", h.federationAPIURL+FederationAPIInputPublicKeyPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpFederationInternalAPI) QueryPublicKeys(
ctx context.Context,
request *api.QueryPublicKeysRequest,
response *api.QueryPublicKeysResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryPublicKeys", h.federationAPIURL+FederationAPIQueryPublicKeyPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpFederationInternalAPI) P2PQueryRelayServers(
ctx context.Context,
request *api.P2PQueryRelayServersRequest,
response *api.P2PQueryRelayServersResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryRelayServers", h.federationAPIURL+FederationAPIQueryRelayServers,
h.httpClient, ctx, request, response,
)
}
func (h *httpFederationInternalAPI) P2PAddRelayServers(
ctx context.Context,
request *api.P2PAddRelayServersRequest,
response *api.P2PAddRelayServersResponse,
) error {
return httputil.CallInternalRPCAPI(
"AddRelayServers", h.federationAPIURL+FederationAPIAddRelayServers,
h.httpClient, ctx, request, response,
)
}
func (h *httpFederationInternalAPI) P2PRemoveRelayServers(
ctx context.Context,
request *api.P2PRemoveRelayServersRequest,
response *api.P2PRemoveRelayServersResponse,
) error {
return httputil.CallInternalRPCAPI(
"RemoveRelayServers", h.federationAPIURL+FederationAPIRemoveRelayServers,
h.httpClient, ctx, request, response,
)
}

View file

@ -1,257 +0,0 @@
package inthttp
import (
"context"
"encoding/json"
"net/http"
"net/url"
"github.com/gorilla/mux"
"github.com/matrix-org/gomatrix"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
"github.com/matrix-org/dendrite/federationapi/api"
"github.com/matrix-org/dendrite/internal/httputil"
)
// AddRoutes adds the FederationInternalAPI handlers to the http.ServeMux.
// nolint:gocyclo
func AddRoutes(intAPI api.FederationInternalAPI, internalAPIMux *mux.Router, enableMetrics bool) {
internalAPIMux.Handle(
FederationAPIQueryJoinedHostServerNamesInRoomPath,
httputil.MakeInternalRPCAPI("FederationAPIQueryJoinedHostServerNamesInRoom", enableMetrics, intAPI.QueryJoinedHostServerNamesInRoom),
)
internalAPIMux.Handle(
FederationAPIPerformInviteRequestPath,
httputil.MakeInternalRPCAPI("FederationAPIPerformInvite", enableMetrics, intAPI.PerformInvite),
)
internalAPIMux.Handle(
FederationAPIPerformLeaveRequestPath,
httputil.MakeInternalRPCAPI("FederationAPIPerformLeave", enableMetrics, intAPI.PerformLeave),
)
internalAPIMux.Handle(
FederationAPIPerformDirectoryLookupRequestPath,
httputil.MakeInternalRPCAPI("FederationAPIPerformDirectoryLookupRequest", enableMetrics, intAPI.PerformDirectoryLookup),
)
internalAPIMux.Handle(
FederationAPIPerformBroadcastEDUPath,
httputil.MakeInternalRPCAPI("FederationAPIPerformBroadcastEDU", enableMetrics, intAPI.PerformBroadcastEDU),
)
internalAPIMux.Handle(
FederationAPIPerformWakeupServers,
httputil.MakeInternalRPCAPI("FederationAPIPerformWakeupServers", enableMetrics, intAPI.PerformWakeupServers),
)
internalAPIMux.Handle(
FederationAPIPerformJoinRequestPath,
httputil.MakeInternalRPCAPI(
"FederationAPIPerformJoinRequest", enableMetrics,
func(ctx context.Context, req *api.PerformJoinRequest, res *api.PerformJoinResponse) error {
intAPI.PerformJoin(ctx, req, res)
return nil
},
),
)
internalAPIMux.Handle(
FederationAPIGetUserDevicesPath,
httputil.MakeInternalProxyAPI(
"FederationAPIGetUserDevices", enableMetrics,
func(ctx context.Context, req *getUserDevices) (*gomatrixserverlib.RespUserDevices, error) {
res, err := intAPI.GetUserDevices(ctx, req.Origin, req.S, req.UserID)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPIClaimKeysPath,
httputil.MakeInternalProxyAPI(
"FederationAPIClaimKeys", enableMetrics,
func(ctx context.Context, req *claimKeys) (*gomatrixserverlib.RespClaimKeys, error) {
res, err := intAPI.ClaimKeys(ctx, req.Origin, req.S, req.OneTimeKeys)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPIQueryKeysPath,
httputil.MakeInternalProxyAPI(
"FederationAPIQueryKeys", enableMetrics,
func(ctx context.Context, req *queryKeys) (*gomatrixserverlib.RespQueryKeys, error) {
res, err := intAPI.QueryKeys(ctx, req.Origin, req.S, req.Keys)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPIBackfillPath,
httputil.MakeInternalProxyAPI(
"FederationAPIBackfill", enableMetrics,
func(ctx context.Context, req *backfill) (*gomatrixserverlib.Transaction, error) {
res, err := intAPI.Backfill(ctx, req.Origin, req.S, req.RoomID, req.Limit, req.EventIDs)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPILookupStatePath,
httputil.MakeInternalProxyAPI(
"FederationAPILookupState", enableMetrics,
func(ctx context.Context, req *lookupState) (*gomatrixserverlib.RespState, error) {
res, err := intAPI.LookupState(ctx, req.Origin, req.S, req.RoomID, req.EventID, req.RoomVersion)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPILookupStateIDsPath,
httputil.MakeInternalProxyAPI(
"FederationAPILookupStateIDs", enableMetrics,
func(ctx context.Context, req *lookupStateIDs) (*gomatrixserverlib.RespStateIDs, error) {
res, err := intAPI.LookupStateIDs(ctx, req.Origin, req.S, req.RoomID, req.EventID)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPILookupMissingEventsPath,
httputil.MakeInternalProxyAPI(
"FederationAPILookupMissingEvents", enableMetrics,
func(ctx context.Context, req *lookupMissingEvents) (*gomatrixserverlib.RespMissingEvents, error) {
res, err := intAPI.LookupMissingEvents(ctx, req.Origin, req.S, req.RoomID, req.Missing, req.RoomVersion)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPIGetEventPath,
httputil.MakeInternalProxyAPI(
"FederationAPIGetEvent", enableMetrics,
func(ctx context.Context, req *getEvent) (*gomatrixserverlib.Transaction, error) {
res, err := intAPI.GetEvent(ctx, req.Origin, req.S, req.EventID)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPIGetEventAuthPath,
httputil.MakeInternalProxyAPI(
"FederationAPIGetEventAuth", enableMetrics,
func(ctx context.Context, req *getEventAuth) (*gomatrixserverlib.RespEventAuth, error) {
res, err := intAPI.GetEventAuth(ctx, req.Origin, req.S, req.RoomVersion, req.RoomID, req.EventID)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPIQueryServerKeysPath,
httputil.MakeInternalRPCAPI("FederationAPIQueryServerKeys", enableMetrics, intAPI.QueryServerKeys),
)
internalAPIMux.Handle(
FederationAPILookupServerKeysPath,
httputil.MakeInternalProxyAPI(
"FederationAPILookupServerKeys", enableMetrics,
func(ctx context.Context, req *lookupServerKeys) (*[]gomatrixserverlib.ServerKeys, error) {
res, err := intAPI.LookupServerKeys(ctx, req.S, req.KeyRequests)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPIEventRelationshipsPath,
httputil.MakeInternalProxyAPI(
"FederationAPIMSC2836EventRelationships", enableMetrics,
func(ctx context.Context, req *eventRelationships) (*gomatrixserverlib.MSC2836EventRelationshipsResponse, error) {
res, err := intAPI.MSC2836EventRelationships(ctx, req.Origin, req.S, req.Req, req.RoomVer)
return &res, federationClientError(err)
},
),
)
internalAPIMux.Handle(
FederationAPISpacesSummaryPath,
httputil.MakeInternalProxyAPI(
"FederationAPIMSC2946SpacesSummary", enableMetrics,
func(ctx context.Context, req *spacesReq) (*gomatrixserverlib.MSC2946SpacesResponse, error) {
res, err := intAPI.MSC2946Spaces(ctx, req.Origin, req.S, req.RoomID, req.SuggestedOnly)
return &res, federationClientError(err)
},
),
)
// TODO: Look at this shape
internalAPIMux.Handle(FederationAPIQueryPublicKeyPath,
httputil.MakeInternalAPI("FederationAPIQueryPublicKeys", enableMetrics, func(req *http.Request) util.JSONResponse {
request := api.QueryPublicKeysRequest{}
response := api.QueryPublicKeysResponse{}
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return util.MessageResponse(http.StatusBadRequest, err.Error())
}
keys, err := intAPI.FetchKeys(req.Context(), request.Requests)
if err != nil {
return util.ErrorResponse(err)
}
response.Results = keys
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
}),
)
// TODO: Look at this shape
internalAPIMux.Handle(FederationAPIInputPublicKeyPath,
httputil.MakeInternalAPI("FederationAPIInputPublicKeys", enableMetrics, func(req *http.Request) util.JSONResponse {
request := api.InputPublicKeysRequest{}
response := api.InputPublicKeysResponse{}
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return util.MessageResponse(http.StatusBadRequest, err.Error())
}
if err := intAPI.StoreKeys(req.Context(), request.Keys); err != nil {
return util.ErrorResponse(err)
}
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
}),
)
}
func federationClientError(err error) error {
switch ferr := err.(type) {
case nil:
return nil
case api.FederationClientError:
return &ferr
case *api.FederationClientError:
return ferr
case gomatrix.HTTPError:
return &api.FederationClientError{
Code: ferr.Code,
}
case *url.Error: // e.g. certificate error, unable to connect
return &api.FederationClientError{
Err: ferr.Error(),
Code: 400,
}
default:
// We don't know what exactly failed, but we probably don't
// want to retry the request immediately in the device list updater
return &api.FederationClientError{
Err: err.Error(),
Code: 400,
}
}
}

2
go.mod
View file

@ -46,7 +46,6 @@ require (
golang.org/x/crypto v0.5.0 golang.org/x/crypto v0.5.0
golang.org/x/image v0.1.0 golang.org/x/image v0.1.0
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e
golang.org/x/net v0.5.0
golang.org/x/term v0.4.0 golang.org/x/term v0.4.0
gopkg.in/h2non/bimg.v1 v1.1.9 gopkg.in/h2non/bimg.v1 v1.1.9
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
@ -124,6 +123,7 @@ require (
go.etcd.io/bbolt v1.3.6 // indirect go.etcd.io/bbolt v1.3.6 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.6.0 // indirect golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/sys v0.4.0 // indirect golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect golang.org/x/text v0.6.0 // indirect
golang.org/x/time v0.1.0 // indirect golang.org/x/time v0.1.0 // indirect

View file

@ -1,93 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package httputil
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
)
// PostJSON performs a POST request with JSON on an internal HTTP API.
// The error will match the errtype if returned from the remote API, or
// will be a different type if there was a problem reaching the API.
func PostJSON[reqtype, restype any, errtype error](
ctx context.Context, span opentracing.Span, httpClient *http.Client,
apiURL string, request *reqtype, response *restype,
) error {
jsonBytes, err := json.Marshal(request)
if err != nil {
return err
}
parsedAPIURL, err := url.Parse(apiURL)
if err != nil {
return err
}
parsedAPIURL.Path = InternalPathPrefix + strings.TrimLeft(parsedAPIURL.Path, "/")
apiURL = parsedAPIURL.String()
req, err := http.NewRequest(http.MethodPost, apiURL, bytes.NewReader(jsonBytes))
if err != nil {
return err
}
// Mark the span as being an RPC client.
ext.SpanKindRPCClient.Set(span)
carrier := opentracing.HTTPHeadersCarrier(req.Header)
tracer := opentracing.GlobalTracer()
if err = tracer.Inject(span.Context(), opentracing.HTTPHeaders, carrier); err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
res, err := httpClient.Do(req.WithContext(ctx))
if res != nil {
defer (func() { err = res.Body.Close() })()
}
if err != nil {
return err
}
var body []byte
body, err = io.ReadAll(res.Body)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
if len(body) == 0 {
return fmt.Errorf("HTTP %d from %s (no response body)", res.StatusCode, apiURL)
}
var reserr errtype
if err = json.Unmarshal(body, &reserr); err != nil {
return fmt.Errorf("HTTP %d from %s - %w", res.StatusCode, apiURL, err)
}
return reserr
}
if err = json.Unmarshal(body, response); err != nil {
return fmt.Errorf("json.Unmarshal: %w", err)
}
return nil
}

View file

@ -1,93 +0,0 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// 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.
package httputil
import (
"context"
"encoding/json"
"fmt"
"net/http"
"reflect"
"github.com/matrix-org/util"
"github.com/opentracing/opentracing-go"
)
type InternalAPIError struct {
Type string
Message string
}
func (e InternalAPIError) Error() string {
return fmt.Sprintf("internal API returned %q error: %s", e.Type, e.Message)
}
func MakeInternalRPCAPI[reqtype, restype any](metricsName string, enableMetrics bool, f func(context.Context, *reqtype, *restype) error) http.Handler {
return MakeInternalAPI(metricsName, enableMetrics, func(req *http.Request) util.JSONResponse {
var request reqtype
var response restype
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return util.MessageResponse(http.StatusBadRequest, err.Error())
}
if err := f(req.Context(), &request, &response); err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: &InternalAPIError{
Type: reflect.TypeOf(err).String(),
Message: fmt.Sprintf("%s", err),
},
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: &response,
}
})
}
func MakeInternalProxyAPI[reqtype, restype any](metricsName string, enableMetrics bool, f func(context.Context, *reqtype) (*restype, error)) http.Handler {
return MakeInternalAPI(metricsName, enableMetrics, func(req *http.Request) util.JSONResponse {
var request reqtype
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return util.MessageResponse(http.StatusBadRequest, err.Error())
}
response, err := f(req.Context(), &request)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: err,
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: response,
}
})
}
func CallInternalRPCAPI[reqtype, restype any](name, url string, client *http.Client, ctx context.Context, request *reqtype, response *restype) error {
span, ctx := opentracing.StartSpanFromContext(ctx, name)
defer span.Finish()
return PostJSON[reqtype, restype, InternalAPIError](ctx, span, client, url, request, response)
}
func CallInternalProxyAPI[reqtype, restype any, errtype error](name, url string, client *http.Client, ctx context.Context, request *reqtype) (restype, error) {
span, ctx := opentracing.StartSpanFromContext(ctx, name)
defer span.Finish()
var response restype
return response, PostJSON[reqtype, restype, errtype](ctx, span, client, url, request, &response)
}

View file

@ -21,7 +21,6 @@ const (
PublicMediaPathPrefix = "/_matrix/media/" PublicMediaPathPrefix = "/_matrix/media/"
PublicStaticPath = "/_matrix/static/" PublicStaticPath = "/_matrix/static/"
PublicWellKnownPrefix = "/.well-known/matrix/" PublicWellKnownPrefix = "/.well-known/matrix/"
InternalPathPrefix = "/api/"
DendriteAdminPathPrefix = "/_dendrite/" DendriteAdminPathPrefix = "/_dendrite/"
SynapseAdminPathPrefix = "/_synapse/" SynapseAdminPathPrefix = "/_synapse/"
) )

View file

@ -129,9 +129,9 @@ func checkFileHookParams(params map[string]interface{}) {
} }
// Add a new FSHook to the logger. Each component will log in its own file // Add a new FSHook to the logger. Each component will log in its own file
func setupFileHook(hook config.LogrusHook, level logrus.Level, componentName string) { func setupFileHook(hook config.LogrusHook, level logrus.Level) {
dirPath := (hook.Params["path"]).(string) dirPath := (hook.Params["path"]).(string)
fullPath := filepath.Join(dirPath, componentName+".log") fullPath := filepath.Join(dirPath, "dendrite.log")
if err := os.MkdirAll(path.Dir(fullPath), os.ModePerm); err != nil { if err := os.MkdirAll(path.Dir(fullPath), os.ModePerm); err != nil {
logrus.Fatalf("Couldn't create directory %s: %q", path.Dir(fullPath), err) logrus.Fatalf("Couldn't create directory %s: %q", path.Dir(fullPath), err)

View file

@ -31,7 +31,7 @@ import (
// SetupHookLogging configures the logging hooks defined in the configuration. // SetupHookLogging configures the logging hooks defined in the configuration.
// If something fails here it means that the logging was improperly configured, // If something fails here it means that the logging was improperly configured,
// so we just exit with the error // so we just exit with the error
func SetupHookLogging(hooks []config.LogrusHook, componentName string) { func SetupHookLogging(hooks []config.LogrusHook) {
levelLogAddedMu.Lock() levelLogAddedMu.Lock()
defer levelLogAddedMu.Unlock() defer levelLogAddedMu.Unlock()
for _, hook := range hooks { for _, hook := range hooks {
@ -50,10 +50,10 @@ func SetupHookLogging(hooks []config.LogrusHook, componentName string) {
switch hook.Type { switch hook.Type {
case "file": case "file":
checkFileHookParams(hook.Params) checkFileHookParams(hook.Params)
setupFileHook(hook, level, componentName) setupFileHook(hook, level)
case "syslog": case "syslog":
checkSyslogHookParams(hook.Params) checkSyslogHookParams(hook.Params)
setupSyslogHook(hook, level, componentName) setupSyslogHook(hook, level)
case "std": case "std":
setupStdLogHook(level) setupStdLogHook(level)
default: default:
@ -94,8 +94,8 @@ func setupStdLogHook(level logrus.Level) {
stdLevelLogAdded[level] = true stdLevelLogAdded[level] = true
} }
func setupSyslogHook(hook config.LogrusHook, level logrus.Level, componentName string) { func setupSyslogHook(hook config.LogrusHook, level logrus.Level) {
syslogHook, err := lSyslog.NewSyslogHook(hook.Params["protocol"].(string), hook.Params["address"].(string), syslog.LOG_INFO, componentName) syslogHook, err := lSyslog.NewSyslogHook(hook.Params["protocol"].(string), hook.Params["address"].(string), syslog.LOG_INFO, "dendrite")
if err == nil { if err == nil {
logrus.AddHook(&logLevelHook{level, syslogHook}) logrus.AddHook(&logLevelHook{level, syslogHook})
} }

View file

@ -22,7 +22,7 @@ import (
// SetupHookLogging configures the logging hooks defined in the configuration. // SetupHookLogging configures the logging hooks defined in the configuration.
// If something fails here it means that the logging was improperly configured, // If something fails here it means that the logging was improperly configured,
// so we just exit with the error // so we just exit with the error
func SetupHookLogging(hooks []config.LogrusHook, componentName string) { func SetupHookLogging(hooks []config.LogrusHook) {
logrus.SetReportCaller(true) logrus.SetReportCaller(true)
for _, hook := range hooks { for _, hook := range hooks {
// Check we received a proper logging level // Check we received a proper logging level
@ -40,7 +40,7 @@ func SetupHookLogging(hooks []config.LogrusHook, componentName string) {
switch hook.Type { switch hook.Type {
case "file": case "file":
checkFileHookParams(hook.Params) checkFileHookParams(hook.Params)
setupFileHook(hook, level, componentName) setupFileHook(hook, level)
default: default:
logrus.Fatalf("Unrecognised logging hook type: %s", hook.Type) logrus.Fatalf("Unrecognised logging hook type: %s", hook.Type)
} }

View file

@ -198,8 +198,8 @@ func TestProcessTransactionRequestPDUSendFail(t *testing.T) {
func createTransactionWithEDU(ctx *process.ProcessContext, edus []gomatrixserverlib.EDU) (TxnReq, nats.JetStreamContext, *config.Dendrite) { func createTransactionWithEDU(ctx *process.ProcessContext, edus []gomatrixserverlib.EDU) (TxnReq, nats.JetStreamContext, *config.Dendrite) {
cfg := &config.Dendrite{} cfg := &config.Dendrite{}
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: true,
}) })
cfg.Global.JetStream.InMemory = true cfg.Global.JetStream.InMemory = true
natsInstance := &jetstream.NATSInstance{} natsInstance := &jetstream.NATSInstance{}
@ -647,7 +647,7 @@ func init() {
} }
type testRoomserverAPI struct { type testRoomserverAPI struct {
rsAPI.RoomserverInternalAPITrace rsAPI.RoomserverInternalAPI
inputRoomEvents []rsAPI.InputRoomEvent inputRoomEvents []rsAPI.InputRoomEvent
queryStateAfterEvents func(*rsAPI.QueryStateAfterEventsRequest) rsAPI.QueryStateAfterEventsResponse queryStateAfterEvents func(*rsAPI.QueryStateAfterEventsRequest) rsAPI.QueryStateAfterEventsResponse
queryEventsByID func(req *rsAPI.QueryEventsByIDRequest) rsAPI.QueryEventsByIDResponse queryEventsByID func(req *rsAPI.QueryEventsByIDRequest) rsAPI.QueryEventsByIDResponse

View file

@ -477,10 +477,6 @@ func (u *DeviceListUpdater) processServerUser(ctx context.Context, serverName go
return e.RetryAfter, err return e.RetryAfter, err
} else if e.Blacklisted { } else if e.Blacklisted {
return time.Hour * 8, err return time.Hour * 8, err
} else if e.Code >= 300 {
// We didn't get a real FederationClientError (e.g. in polylith mode, where gomatrix.HTTPError
// are "converted" to FederationClientError), but we probably shouldn't hit them every $waitTime seconds.
return hourWaitTime, err
} }
case net.Error: case net.Error:
// Use the default waitTime, if it's a timeout. // Use the default waitTime, if it's a timeout.

View file

@ -1,186 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package inthttp
import (
"context"
"errors"
"net/http"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/keyserver/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
)
// HTTP paths for the internal HTTP APIs
const (
InputDeviceListUpdatePath = "/keyserver/inputDeviceListUpdate"
PerformUploadKeysPath = "/keyserver/performUploadKeys"
PerformClaimKeysPath = "/keyserver/performClaimKeys"
PerformDeleteKeysPath = "/keyserver/performDeleteKeys"
PerformUploadDeviceKeysPath = "/keyserver/performUploadDeviceKeys"
PerformUploadDeviceSignaturesPath = "/keyserver/performUploadDeviceSignatures"
QueryKeysPath = "/keyserver/queryKeys"
QueryKeyChangesPath = "/keyserver/queryKeyChanges"
QueryOneTimeKeysPath = "/keyserver/queryOneTimeKeys"
QueryDeviceMessagesPath = "/keyserver/queryDeviceMessages"
QuerySignaturesPath = "/keyserver/querySignatures"
PerformMarkAsStalePath = "/keyserver/markAsStale"
)
// NewKeyServerClient creates a KeyInternalAPI implemented by talking to a HTTP POST API.
// If httpClient is nil an error is returned
func NewKeyServerClient(
apiURL string,
httpClient *http.Client,
) (api.KeyInternalAPI, error) {
if httpClient == nil {
return nil, errors.New("NewKeyServerClient: httpClient is <nil>")
}
return &httpKeyInternalAPI{
apiURL: apiURL,
httpClient: httpClient,
}, nil
}
type httpKeyInternalAPI struct {
apiURL string
httpClient *http.Client
}
func (h *httpKeyInternalAPI) SetUserAPI(i userapi.KeyserverUserAPI) {
// no-op: doesn't need it
}
func (h *httpKeyInternalAPI) PerformClaimKeys(
ctx context.Context,
request *api.PerformClaimKeysRequest,
response *api.PerformClaimKeysResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformClaimKeys", h.apiURL+PerformClaimKeysPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) PerformDeleteKeys(
ctx context.Context,
request *api.PerformDeleteKeysRequest,
response *api.PerformDeleteKeysResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformDeleteKeys", h.apiURL+PerformDeleteKeysPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) PerformUploadKeys(
ctx context.Context,
request *api.PerformUploadKeysRequest,
response *api.PerformUploadKeysResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformUploadKeys", h.apiURL+PerformUploadKeysPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) QueryKeys(
ctx context.Context,
request *api.QueryKeysRequest,
response *api.QueryKeysResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryKeys", h.apiURL+QueryKeysPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) QueryOneTimeKeys(
ctx context.Context,
request *api.QueryOneTimeKeysRequest,
response *api.QueryOneTimeKeysResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryOneTimeKeys", h.apiURL+QueryOneTimeKeysPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) QueryDeviceMessages(
ctx context.Context,
request *api.QueryDeviceMessagesRequest,
response *api.QueryDeviceMessagesResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryDeviceMessages", h.apiURL+QueryDeviceMessagesPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) QueryKeyChanges(
ctx context.Context,
request *api.QueryKeyChangesRequest,
response *api.QueryKeyChangesResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryKeyChanges", h.apiURL+QueryKeyChangesPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) PerformUploadDeviceKeys(
ctx context.Context,
request *api.PerformUploadDeviceKeysRequest,
response *api.PerformUploadDeviceKeysResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformUploadDeviceKeys", h.apiURL+PerformUploadDeviceKeysPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) PerformUploadDeviceSignatures(
ctx context.Context,
request *api.PerformUploadDeviceSignaturesRequest,
response *api.PerformUploadDeviceSignaturesResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformUploadDeviceSignatures", h.apiURL+PerformUploadDeviceSignaturesPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) QuerySignatures(
ctx context.Context,
request *api.QuerySignaturesRequest,
response *api.QuerySignaturesResponse,
) error {
return httputil.CallInternalRPCAPI(
"QuerySignatures", h.apiURL+QuerySignaturesPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpKeyInternalAPI) PerformMarkAsStaleIfNeeded(
ctx context.Context,
request *api.PerformMarkAsStaleRequest,
response *struct{},
) error {
return httputil.CallInternalRPCAPI(
"MarkAsStale", h.apiURL+PerformMarkAsStalePath,
h.httpClient, ctx, request, response,
)
}

View file

@ -1,79 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package inthttp
import (
"github.com/gorilla/mux"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/keyserver/api"
)
func AddRoutes(internalAPIMux *mux.Router, s api.KeyInternalAPI, enableMetrics bool) {
internalAPIMux.Handle(
PerformClaimKeysPath,
httputil.MakeInternalRPCAPI("KeyserverPerformClaimKeys", enableMetrics, s.PerformClaimKeys),
)
internalAPIMux.Handle(
PerformDeleteKeysPath,
httputil.MakeInternalRPCAPI("KeyserverPerformDeleteKeys", enableMetrics, s.PerformDeleteKeys),
)
internalAPIMux.Handle(
PerformUploadKeysPath,
httputil.MakeInternalRPCAPI("KeyserverPerformUploadKeys", enableMetrics, s.PerformUploadKeys),
)
internalAPIMux.Handle(
PerformUploadDeviceKeysPath,
httputil.MakeInternalRPCAPI("KeyserverPerformUploadDeviceKeys", enableMetrics, s.PerformUploadDeviceKeys),
)
internalAPIMux.Handle(
PerformUploadDeviceSignaturesPath,
httputil.MakeInternalRPCAPI("KeyserverPerformUploadDeviceSignatures", enableMetrics, s.PerformUploadDeviceSignatures),
)
internalAPIMux.Handle(
QueryKeysPath,
httputil.MakeInternalRPCAPI("KeyserverQueryKeys", enableMetrics, s.QueryKeys),
)
internalAPIMux.Handle(
QueryOneTimeKeysPath,
httputil.MakeInternalRPCAPI("KeyserverQueryOneTimeKeys", enableMetrics, s.QueryOneTimeKeys),
)
internalAPIMux.Handle(
QueryDeviceMessagesPath,
httputil.MakeInternalRPCAPI("KeyserverQueryDeviceMessages", enableMetrics, s.QueryDeviceMessages),
)
internalAPIMux.Handle(
QueryKeyChangesPath,
httputil.MakeInternalRPCAPI("KeyserverQueryKeyChanges", enableMetrics, s.QueryKeyChanges),
)
internalAPIMux.Handle(
QuerySignaturesPath,
httputil.MakeInternalRPCAPI("KeyserverQuerySignatures", enableMetrics, s.QuerySignatures),
)
internalAPIMux.Handle(
PerformMarkAsStalePath,
httputil.MakeInternalRPCAPI("KeyserverMarkAsStale", enableMetrics, s.PerformMarkAsStaleIfNeeded),
)
}

View file

@ -15,7 +15,6 @@
package keyserver package keyserver
import ( import (
"github.com/gorilla/mux"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
rsapi "github.com/matrix-org/dendrite/roomserver/api" rsapi "github.com/matrix-org/dendrite/roomserver/api"
@ -24,7 +23,6 @@ import (
"github.com/matrix-org/dendrite/keyserver/api" "github.com/matrix-org/dendrite/keyserver/api"
"github.com/matrix-org/dendrite/keyserver/consumers" "github.com/matrix-org/dendrite/keyserver/consumers"
"github.com/matrix-org/dendrite/keyserver/internal" "github.com/matrix-org/dendrite/keyserver/internal"
"github.com/matrix-org/dendrite/keyserver/inthttp"
"github.com/matrix-org/dendrite/keyserver/producers" "github.com/matrix-org/dendrite/keyserver/producers"
"github.com/matrix-org/dendrite/keyserver/storage" "github.com/matrix-org/dendrite/keyserver/storage"
"github.com/matrix-org/dendrite/setup/base" "github.com/matrix-org/dendrite/setup/base"
@ -32,12 +30,6 @@ import (
"github.com/matrix-org/dendrite/setup/jetstream" "github.com/matrix-org/dendrite/setup/jetstream"
) )
// AddInternalRoutes registers HTTP handlers for the internal API. Invokes functions
// on the given input API.
func AddInternalRoutes(router *mux.Router, intAPI api.KeyInternalAPI, enableMetrics bool) {
inthttp.AddRoutes(router, intAPI, enableMetrics)
}
// NewInternalAPI returns a concerete implementation of the internal API. Callers // NewInternalAPI returns a concerete implementation of the internal API. Callers
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes. // can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
func NewInternalAPI( func NewInternalAPI(

View file

@ -1,427 +0,0 @@
package api
import (
"context"
"encoding/json"
"fmt"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
asAPI "github.com/matrix-org/dendrite/appservice/api"
fsAPI "github.com/matrix-org/dendrite/federationapi/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
)
// RoomserverInternalAPITrace wraps a RoomserverInternalAPI and logs the
// complete request/response/error
type RoomserverInternalAPITrace struct {
Impl RoomserverInternalAPI
}
func (t *RoomserverInternalAPITrace) QueryLeftUsers(ctx context.Context, req *QueryLeftUsersRequest, res *QueryLeftUsersResponse) error {
err := t.Impl.QueryLeftUsers(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryLeftUsers req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) SetFederationAPI(fsAPI fsAPI.RoomserverFederationAPI, keyRing *gomatrixserverlib.KeyRing) {
t.Impl.SetFederationAPI(fsAPI, keyRing)
}
func (t *RoomserverInternalAPITrace) SetAppserviceAPI(asAPI asAPI.AppServiceInternalAPI) {
t.Impl.SetAppserviceAPI(asAPI)
}
func (t *RoomserverInternalAPITrace) SetUserAPI(userAPI userapi.RoomserverUserAPI) {
t.Impl.SetUserAPI(userAPI)
}
func (t *RoomserverInternalAPITrace) InputRoomEvents(
ctx context.Context,
req *InputRoomEventsRequest,
res *InputRoomEventsResponse,
) error {
err := t.Impl.InputRoomEvents(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("InputRoomEvents req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformInvite(
ctx context.Context,
req *PerformInviteRequest,
res *PerformInviteResponse,
) error {
err := t.Impl.PerformInvite(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformInvite req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformPeek(
ctx context.Context,
req *PerformPeekRequest,
res *PerformPeekResponse,
) error {
err := t.Impl.PerformPeek(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformPeek req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformUnpeek(
ctx context.Context,
req *PerformUnpeekRequest,
res *PerformUnpeekResponse,
) error {
err := t.Impl.PerformUnpeek(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformUnpeek req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformRoomUpgrade(
ctx context.Context,
req *PerformRoomUpgradeRequest,
res *PerformRoomUpgradeResponse,
) error {
err := t.Impl.PerformRoomUpgrade(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformRoomUpgrade req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformJoin(
ctx context.Context,
req *PerformJoinRequest,
res *PerformJoinResponse,
) error {
err := t.Impl.PerformJoin(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformJoin req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformLeave(
ctx context.Context,
req *PerformLeaveRequest,
res *PerformLeaveResponse,
) error {
err := t.Impl.PerformLeave(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformLeave req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformPublish(
ctx context.Context,
req *PerformPublishRequest,
res *PerformPublishResponse,
) error {
err := t.Impl.PerformPublish(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformPublish req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformAdminEvacuateRoom(
ctx context.Context,
req *PerformAdminEvacuateRoomRequest,
res *PerformAdminEvacuateRoomResponse,
) error {
err := t.Impl.PerformAdminEvacuateRoom(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformAdminEvacuateRoom req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformAdminEvacuateUser(
ctx context.Context,
req *PerformAdminEvacuateUserRequest,
res *PerformAdminEvacuateUserResponse,
) error {
err := t.Impl.PerformAdminEvacuateUser(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformAdminEvacuateUser req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformAdminPurgeRoom(
ctx context.Context,
req *PerformAdminPurgeRoomRequest,
res *PerformAdminPurgeRoomResponse,
) error {
err := t.Impl.PerformAdminPurgeRoom(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformAdminPurgeRoom req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformAdminDownloadState(
ctx context.Context,
req *PerformAdminDownloadStateRequest,
res *PerformAdminDownloadStateResponse,
) error {
err := t.Impl.PerformAdminDownloadState(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformAdminDownloadState req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformInboundPeek(
ctx context.Context,
req *PerformInboundPeekRequest,
res *PerformInboundPeekResponse,
) error {
err := t.Impl.PerformInboundPeek(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformInboundPeek req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryPublishedRooms(
ctx context.Context,
req *QueryPublishedRoomsRequest,
res *QueryPublishedRoomsResponse,
) error {
err := t.Impl.QueryPublishedRooms(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryPublishedRooms req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryLatestEventsAndState(
ctx context.Context,
req *QueryLatestEventsAndStateRequest,
res *QueryLatestEventsAndStateResponse,
) error {
err := t.Impl.QueryLatestEventsAndState(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryLatestEventsAndState req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryStateAfterEvents(
ctx context.Context,
req *QueryStateAfterEventsRequest,
res *QueryStateAfterEventsResponse,
) error {
err := t.Impl.QueryStateAfterEvents(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryStateAfterEvents req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryEventsByID(
ctx context.Context,
req *QueryEventsByIDRequest,
res *QueryEventsByIDResponse,
) error {
err := t.Impl.QueryEventsByID(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryEventsByID req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryMembershipForUser(
ctx context.Context,
req *QueryMembershipForUserRequest,
res *QueryMembershipForUserResponse,
) error {
err := t.Impl.QueryMembershipForUser(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryMembershipForUser req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryMembershipsForRoom(
ctx context.Context,
req *QueryMembershipsForRoomRequest,
res *QueryMembershipsForRoomResponse,
) error {
err := t.Impl.QueryMembershipsForRoom(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryMembershipsForRoom req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryServerJoinedToRoom(
ctx context.Context,
req *QueryServerJoinedToRoomRequest,
res *QueryServerJoinedToRoomResponse,
) error {
err := t.Impl.QueryServerJoinedToRoom(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryServerJoinedToRoom req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryServerAllowedToSeeEvent(
ctx context.Context,
req *QueryServerAllowedToSeeEventRequest,
res *QueryServerAllowedToSeeEventResponse,
) error {
err := t.Impl.QueryServerAllowedToSeeEvent(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryServerAllowedToSeeEvent req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryMissingEvents(
ctx context.Context,
req *QueryMissingEventsRequest,
res *QueryMissingEventsResponse,
) error {
err := t.Impl.QueryMissingEvents(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryMissingEvents req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryStateAndAuthChain(
ctx context.Context,
req *QueryStateAndAuthChainRequest,
res *QueryStateAndAuthChainResponse,
) error {
err := t.Impl.QueryStateAndAuthChain(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryStateAndAuthChain req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformBackfill(
ctx context.Context,
req *PerformBackfillRequest,
res *PerformBackfillResponse,
) error {
err := t.Impl.PerformBackfill(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformBackfill req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) PerformForget(
ctx context.Context,
req *PerformForgetRequest,
res *PerformForgetResponse,
) error {
err := t.Impl.PerformForget(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("PerformForget req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryRoomVersionCapabilities(
ctx context.Context,
req *QueryRoomVersionCapabilitiesRequest,
res *QueryRoomVersionCapabilitiesResponse,
) error {
err := t.Impl.QueryRoomVersionCapabilities(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryRoomVersionCapabilities req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryRoomVersionForRoom(
ctx context.Context,
req *QueryRoomVersionForRoomRequest,
res *QueryRoomVersionForRoomResponse,
) error {
err := t.Impl.QueryRoomVersionForRoom(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryRoomVersionForRoom req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) SetRoomAlias(
ctx context.Context,
req *SetRoomAliasRequest,
res *SetRoomAliasResponse,
) error {
err := t.Impl.SetRoomAlias(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("SetRoomAlias req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) GetRoomIDForAlias(
ctx context.Context,
req *GetRoomIDForAliasRequest,
res *GetRoomIDForAliasResponse,
) error {
err := t.Impl.GetRoomIDForAlias(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("GetRoomIDForAlias req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) GetAliasesForRoomID(
ctx context.Context,
req *GetAliasesForRoomIDRequest,
res *GetAliasesForRoomIDResponse,
) error {
err := t.Impl.GetAliasesForRoomID(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("GetAliasesForRoomID req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) RemoveRoomAlias(
ctx context.Context,
req *RemoveRoomAliasRequest,
res *RemoveRoomAliasResponse,
) error {
err := t.Impl.RemoveRoomAlias(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("RemoveRoomAlias req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryCurrentState(ctx context.Context, req *QueryCurrentStateRequest, res *QueryCurrentStateResponse) error {
err := t.Impl.QueryCurrentState(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryCurrentState req=%+v res=%+v", js(req), js(res))
return err
}
// QueryRoomsForUser retrieves a list of room IDs matching the given query.
func (t *RoomserverInternalAPITrace) QueryRoomsForUser(ctx context.Context, req *QueryRoomsForUserRequest, res *QueryRoomsForUserResponse) error {
err := t.Impl.QueryRoomsForUser(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryRoomsForUser req=%+v res=%+v", js(req), js(res))
return err
}
// QueryBulkStateContent does a bulk query for state event content in the given rooms.
func (t *RoomserverInternalAPITrace) QueryBulkStateContent(ctx context.Context, req *QueryBulkStateContentRequest, res *QueryBulkStateContentResponse) error {
err := t.Impl.QueryBulkStateContent(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryBulkStateContent req=%+v res=%+v", js(req), js(res))
return err
}
// QuerySharedUsers returns a list of users who share at least 1 room in common with the given user.
func (t *RoomserverInternalAPITrace) QuerySharedUsers(ctx context.Context, req *QuerySharedUsersRequest, res *QuerySharedUsersResponse) error {
err := t.Impl.QuerySharedUsers(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QuerySharedUsers req=%+v res=%+v", js(req), js(res))
return err
}
// QueryKnownUsers returns a list of users that we know about from our joined rooms.
func (t *RoomserverInternalAPITrace) QueryKnownUsers(ctx context.Context, req *QueryKnownUsersRequest, res *QueryKnownUsersResponse) error {
err := t.Impl.QueryKnownUsers(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryKnownUsers req=%+v res=%+v", js(req), js(res))
return err
}
// QueryServerBannedFromRoom returns whether a server is banned from a room by server ACLs.
func (t *RoomserverInternalAPITrace) QueryServerBannedFromRoom(ctx context.Context, req *QueryServerBannedFromRoomRequest, res *QueryServerBannedFromRoomResponse) error {
err := t.Impl.QueryServerBannedFromRoom(ctx, req, res)
util.GetLogger(ctx).WithError(err).Infof("QueryServerBannedFromRoom req=%+v res=%+v", js(req), js(res))
return err
}
func (t *RoomserverInternalAPITrace) QueryAuthChain(
ctx context.Context,
request *QueryAuthChainRequest,
response *QueryAuthChainResponse,
) error {
err := t.Impl.QueryAuthChain(ctx, request, response)
util.GetLogger(ctx).WithError(err).Infof("QueryAuthChain req=%+v res=%+v", js(request), js(response))
return err
}
func (t *RoomserverInternalAPITrace) QueryRestrictedJoinAllowed(
ctx context.Context,
request *QueryRestrictedJoinAllowedRequest,
response *QueryRestrictedJoinAllowedResponse,
) error {
err := t.Impl.QueryRestrictedJoinAllowed(ctx, request, response)
util.GetLogger(ctx).WithError(err).Infof("QueryRestrictedJoinAllowed req=%+v res=%+v", js(request), js(response))
return err
}
func (t *RoomserverInternalAPITrace) QueryMembershipAtEvent(
ctx context.Context,
request *QueryMembershipAtEventRequest,
response *QueryMembershipAtEventResponse,
) error {
err := t.Impl.QueryMembershipAtEvent(ctx, request, response)
util.GetLogger(ctx).WithError(err).Infof("QueryMembershipAtEvent req=%+v res=%+v", js(request), js(response))
return err
}
func js(thing interface{}) string {
b, err := json.Marshal(thing)
if err != nil {
return fmt.Sprintf("Marshal error:%s", err)
}
return string(b)
}

View file

@ -1,575 +0,0 @@
package inthttp
import (
"context"
"errors"
"net/http"
"github.com/matrix-org/gomatrixserverlib"
asAPI "github.com/matrix-org/dendrite/appservice/api"
fsInputAPI "github.com/matrix-org/dendrite/federationapi/api"
"github.com/matrix-org/dendrite/internal/caching"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/roomserver/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
)
const (
// Alias operations
RoomserverSetRoomAliasPath = "/roomserver/setRoomAlias"
RoomserverGetRoomIDForAliasPath = "/roomserver/GetRoomIDForAlias"
RoomserverGetAliasesForRoomIDPath = "/roomserver/GetAliasesForRoomID"
RoomserverGetCreatorIDForAliasPath = "/roomserver/GetCreatorIDForAlias"
RoomserverRemoveRoomAliasPath = "/roomserver/removeRoomAlias"
// Input operations
RoomserverInputRoomEventsPath = "/roomserver/inputRoomEvents"
// Perform operations
RoomserverPerformInvitePath = "/roomserver/performInvite"
RoomserverPerformPeekPath = "/roomserver/performPeek"
RoomserverPerformUnpeekPath = "/roomserver/performUnpeek"
RoomserverPerformRoomUpgradePath = "/roomserver/performRoomUpgrade"
RoomserverPerformJoinPath = "/roomserver/performJoin"
RoomserverPerformLeavePath = "/roomserver/performLeave"
RoomserverPerformBackfillPath = "/roomserver/performBackfill"
RoomserverPerformPublishPath = "/roomserver/performPublish"
RoomserverPerformInboundPeekPath = "/roomserver/performInboundPeek"
RoomserverPerformForgetPath = "/roomserver/performForget"
RoomserverPerformAdminEvacuateRoomPath = "/roomserver/performAdminEvacuateRoom"
RoomserverPerformAdminEvacuateUserPath = "/roomserver/performAdminEvacuateUser"
RoomserverPerformAdminDownloadStatePath = "/roomserver/performAdminDownloadState"
RoomserverPerformAdminPurgeRoomPath = "/roomserver/performAdminPurgeRoom"
// Query operations
RoomserverQueryLatestEventsAndStatePath = "/roomserver/queryLatestEventsAndState"
RoomserverQueryStateAfterEventsPath = "/roomserver/queryStateAfterEvents"
RoomserverQueryEventsByIDPath = "/roomserver/queryEventsByID"
RoomserverQueryMembershipForUserPath = "/roomserver/queryMembershipForUser"
RoomserverQueryMembershipsForRoomPath = "/roomserver/queryMembershipsForRoom"
RoomserverQueryServerJoinedToRoomPath = "/roomserver/queryServerJoinedToRoomPath"
RoomserverQueryServerAllowedToSeeEventPath = "/roomserver/queryServerAllowedToSeeEvent"
RoomserverQueryMissingEventsPath = "/roomserver/queryMissingEvents"
RoomserverQueryStateAndAuthChainPath = "/roomserver/queryStateAndAuthChain"
RoomserverQueryRoomVersionCapabilitiesPath = "/roomserver/queryRoomVersionCapabilities"
RoomserverQueryRoomVersionForRoomPath = "/roomserver/queryRoomVersionForRoom"
RoomserverQueryPublishedRoomsPath = "/roomserver/queryPublishedRooms"
RoomserverQueryCurrentStatePath = "/roomserver/queryCurrentState"
RoomserverQueryRoomsForUserPath = "/roomserver/queryRoomsForUser"
RoomserverQueryBulkStateContentPath = "/roomserver/queryBulkStateContent"
RoomserverQuerySharedUsersPath = "/roomserver/querySharedUsers"
RoomserverQueryKnownUsersPath = "/roomserver/queryKnownUsers"
RoomserverQueryServerBannedFromRoomPath = "/roomserver/queryServerBannedFromRoom"
RoomserverQueryAuthChainPath = "/roomserver/queryAuthChain"
RoomserverQueryRestrictedJoinAllowed = "/roomserver/queryRestrictedJoinAllowed"
RoomserverQueryMembershipAtEventPath = "/roomserver/queryMembershipAtEvent"
RoomserverQueryLeftMembersPath = "/roomserver/queryLeftMembers"
)
type httpRoomserverInternalAPI struct {
roomserverURL string
httpClient *http.Client
cache caching.RoomVersionCache
}
// NewRoomserverClient creates a RoomserverInputAPI implemented by talking to a HTTP POST API.
// If httpClient is nil an error is returned
func NewRoomserverClient(
roomserverURL string,
httpClient *http.Client,
cache caching.RoomVersionCache,
) (api.RoomserverInternalAPI, error) {
if httpClient == nil {
return nil, errors.New("NewRoomserverInternalAPIHTTP: httpClient is <nil>")
}
return &httpRoomserverInternalAPI{
roomserverURL: roomserverURL,
httpClient: httpClient,
cache: cache,
}, nil
}
// SetFederationInputAPI no-ops in HTTP client mode as there is no chicken/egg scenario
func (h *httpRoomserverInternalAPI) SetFederationAPI(fsAPI fsInputAPI.RoomserverFederationAPI, keyRing *gomatrixserverlib.KeyRing) {
}
// SetAppserviceAPI no-ops in HTTP client mode as there is no chicken/egg scenario
func (h *httpRoomserverInternalAPI) SetAppserviceAPI(asAPI asAPI.AppServiceInternalAPI) {
}
// SetUserAPI no-ops in HTTP client mode as there is no chicken/egg scenario
func (h *httpRoomserverInternalAPI) SetUserAPI(userAPI userapi.RoomserverUserAPI) {
}
// SetRoomAlias implements RoomserverAliasAPI
func (h *httpRoomserverInternalAPI) SetRoomAlias(
ctx context.Context,
request *api.SetRoomAliasRequest,
response *api.SetRoomAliasResponse,
) error {
return httputil.CallInternalRPCAPI(
"SetRoomAlias", h.roomserverURL+RoomserverSetRoomAliasPath,
h.httpClient, ctx, request, response,
)
}
// GetRoomIDForAlias implements RoomserverAliasAPI
func (h *httpRoomserverInternalAPI) GetRoomIDForAlias(
ctx context.Context,
request *api.GetRoomIDForAliasRequest,
response *api.GetRoomIDForAliasResponse,
) error {
return httputil.CallInternalRPCAPI(
"GetRoomIDForAlias", h.roomserverURL+RoomserverGetRoomIDForAliasPath,
h.httpClient, ctx, request, response,
)
}
// GetAliasesForRoomID implements RoomserverAliasAPI
func (h *httpRoomserverInternalAPI) GetAliasesForRoomID(
ctx context.Context,
request *api.GetAliasesForRoomIDRequest,
response *api.GetAliasesForRoomIDResponse,
) error {
return httputil.CallInternalRPCAPI(
"GetAliasesForRoomID", h.roomserverURL+RoomserverGetAliasesForRoomIDPath,
h.httpClient, ctx, request, response,
)
}
// RemoveRoomAlias implements RoomserverAliasAPI
func (h *httpRoomserverInternalAPI) RemoveRoomAlias(
ctx context.Context,
request *api.RemoveRoomAliasRequest,
response *api.RemoveRoomAliasResponse,
) error {
return httputil.CallInternalRPCAPI(
"RemoveRoomAlias", h.roomserverURL+RoomserverRemoveRoomAliasPath,
h.httpClient, ctx, request, response,
)
}
// InputRoomEvents implements RoomserverInputAPI
func (h *httpRoomserverInternalAPI) InputRoomEvents(
ctx context.Context,
request *api.InputRoomEventsRequest,
response *api.InputRoomEventsResponse,
) error {
if err := httputil.CallInternalRPCAPI(
"InputRoomEvents", h.roomserverURL+RoomserverInputRoomEventsPath,
h.httpClient, ctx, request, response,
); err != nil {
response.ErrMsg = err.Error()
}
return nil
}
func (h *httpRoomserverInternalAPI) PerformInvite(
ctx context.Context,
request *api.PerformInviteRequest,
response *api.PerformInviteResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformInvite", h.roomserverURL+RoomserverPerformInvitePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformJoin(
ctx context.Context,
request *api.PerformJoinRequest,
response *api.PerformJoinResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformJoin", h.roomserverURL+RoomserverPerformJoinPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformPeek(
ctx context.Context,
request *api.PerformPeekRequest,
response *api.PerformPeekResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformPeek", h.roomserverURL+RoomserverPerformPeekPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformInboundPeek(
ctx context.Context,
request *api.PerformInboundPeekRequest,
response *api.PerformInboundPeekResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformInboundPeek", h.roomserverURL+RoomserverPerformInboundPeekPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformUnpeek(
ctx context.Context,
request *api.PerformUnpeekRequest,
response *api.PerformUnpeekResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformUnpeek", h.roomserverURL+RoomserverPerformUnpeekPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformRoomUpgrade(
ctx context.Context,
request *api.PerformRoomUpgradeRequest,
response *api.PerformRoomUpgradeResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformRoomUpgrade", h.roomserverURL+RoomserverPerformRoomUpgradePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformLeave(
ctx context.Context,
request *api.PerformLeaveRequest,
response *api.PerformLeaveResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformLeave", h.roomserverURL+RoomserverPerformLeavePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformPublish(
ctx context.Context,
request *api.PerformPublishRequest,
response *api.PerformPublishResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformPublish", h.roomserverURL+RoomserverPerformPublishPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformAdminEvacuateRoom(
ctx context.Context,
request *api.PerformAdminEvacuateRoomRequest,
response *api.PerformAdminEvacuateRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAdminEvacuateRoom", h.roomserverURL+RoomserverPerformAdminEvacuateRoomPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformAdminDownloadState(
ctx context.Context,
request *api.PerformAdminDownloadStateRequest,
response *api.PerformAdminDownloadStateResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAdminDownloadState", h.roomserverURL+RoomserverPerformAdminDownloadStatePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformAdminEvacuateUser(
ctx context.Context,
request *api.PerformAdminEvacuateUserRequest,
response *api.PerformAdminEvacuateUserResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAdminEvacuateUser", h.roomserverURL+RoomserverPerformAdminEvacuateUserPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformAdminPurgeRoom(
ctx context.Context,
request *api.PerformAdminPurgeRoomRequest,
response *api.PerformAdminPurgeRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAdminPurgeRoom", h.roomserverURL+RoomserverPerformAdminPurgeRoomPath,
h.httpClient, ctx, request, response,
)
}
// QueryLatestEventsAndState implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryLatestEventsAndState(
ctx context.Context,
request *api.QueryLatestEventsAndStateRequest,
response *api.QueryLatestEventsAndStateResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryLatestEventsAndState", h.roomserverURL+RoomserverQueryLatestEventsAndStatePath,
h.httpClient, ctx, request, response,
)
}
// QueryStateAfterEvents implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryStateAfterEvents(
ctx context.Context,
request *api.QueryStateAfterEventsRequest,
response *api.QueryStateAfterEventsResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryStateAfterEvents", h.roomserverURL+RoomserverQueryStateAfterEventsPath,
h.httpClient, ctx, request, response,
)
}
// QueryEventsByID implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryEventsByID(
ctx context.Context,
request *api.QueryEventsByIDRequest,
response *api.QueryEventsByIDResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryEventsByID", h.roomserverURL+RoomserverQueryEventsByIDPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryPublishedRooms(
ctx context.Context,
request *api.QueryPublishedRoomsRequest,
response *api.QueryPublishedRoomsResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryPublishedRooms", h.roomserverURL+RoomserverQueryPublishedRoomsPath,
h.httpClient, ctx, request, response,
)
}
// QueryMembershipForUser implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryMembershipForUser(
ctx context.Context,
request *api.QueryMembershipForUserRequest,
response *api.QueryMembershipForUserResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryMembershipForUser", h.roomserverURL+RoomserverQueryMembershipForUserPath,
h.httpClient, ctx, request, response,
)
}
// QueryMembershipsForRoom implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryMembershipsForRoom(
ctx context.Context,
request *api.QueryMembershipsForRoomRequest,
response *api.QueryMembershipsForRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryMembershipsForRoom", h.roomserverURL+RoomserverQueryMembershipsForRoomPath,
h.httpClient, ctx, request, response,
)
}
// QueryMembershipsForRoom implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryServerJoinedToRoom(
ctx context.Context,
request *api.QueryServerJoinedToRoomRequest,
response *api.QueryServerJoinedToRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryServerJoinedToRoom", h.roomserverURL+RoomserverQueryServerJoinedToRoomPath,
h.httpClient, ctx, request, response,
)
}
// QueryServerAllowedToSeeEvent implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryServerAllowedToSeeEvent(
ctx context.Context,
request *api.QueryServerAllowedToSeeEventRequest,
response *api.QueryServerAllowedToSeeEventResponse,
) (err error) {
return httputil.CallInternalRPCAPI(
"QueryServerAllowedToSeeEvent", h.roomserverURL+RoomserverQueryServerAllowedToSeeEventPath,
h.httpClient, ctx, request, response,
)
}
// QueryMissingEvents implements RoomServerQueryAPI
func (h *httpRoomserverInternalAPI) QueryMissingEvents(
ctx context.Context,
request *api.QueryMissingEventsRequest,
response *api.QueryMissingEventsResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryMissingEvents", h.roomserverURL+RoomserverQueryMissingEventsPath,
h.httpClient, ctx, request, response,
)
}
// QueryStateAndAuthChain implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryStateAndAuthChain(
ctx context.Context,
request *api.QueryStateAndAuthChainRequest,
response *api.QueryStateAndAuthChainResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryStateAndAuthChain", h.roomserverURL+RoomserverQueryStateAndAuthChainPath,
h.httpClient, ctx, request, response,
)
}
// PerformBackfill implements RoomServerQueryAPI
func (h *httpRoomserverInternalAPI) PerformBackfill(
ctx context.Context,
request *api.PerformBackfillRequest,
response *api.PerformBackfillResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformBackfill", h.roomserverURL+RoomserverPerformBackfillPath,
h.httpClient, ctx, request, response,
)
}
// QueryRoomVersionCapabilities implements RoomServerQueryAPI
func (h *httpRoomserverInternalAPI) QueryRoomVersionCapabilities(
ctx context.Context,
request *api.QueryRoomVersionCapabilitiesRequest,
response *api.QueryRoomVersionCapabilitiesResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryRoomVersionCapabilities", h.roomserverURL+RoomserverQueryRoomVersionCapabilitiesPath,
h.httpClient, ctx, request, response,
)
}
// QueryRoomVersionForRoom implements RoomServerQueryAPI
func (h *httpRoomserverInternalAPI) QueryRoomVersionForRoom(
ctx context.Context,
request *api.QueryRoomVersionForRoomRequest,
response *api.QueryRoomVersionForRoomResponse,
) error {
if roomVersion, ok := h.cache.GetRoomVersion(request.RoomID); ok {
response.RoomVersion = roomVersion
return nil
}
err := httputil.CallInternalRPCAPI(
"QueryRoomVersionForRoom", h.roomserverURL+RoomserverQueryRoomVersionForRoomPath,
h.httpClient, ctx, request, response,
)
if err == nil {
h.cache.StoreRoomVersion(request.RoomID, response.RoomVersion)
}
return err
}
func (h *httpRoomserverInternalAPI) QueryCurrentState(
ctx context.Context,
request *api.QueryCurrentStateRequest,
response *api.QueryCurrentStateResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryCurrentState", h.roomserverURL+RoomserverQueryCurrentStatePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryRoomsForUser(
ctx context.Context,
request *api.QueryRoomsForUserRequest,
response *api.QueryRoomsForUserResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryRoomsForUser", h.roomserverURL+RoomserverQueryRoomsForUserPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryBulkStateContent(
ctx context.Context,
request *api.QueryBulkStateContentRequest,
response *api.QueryBulkStateContentResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryBulkStateContent", h.roomserverURL+RoomserverQueryBulkStateContentPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QuerySharedUsers(
ctx context.Context,
request *api.QuerySharedUsersRequest,
response *api.QuerySharedUsersResponse,
) error {
return httputil.CallInternalRPCAPI(
"QuerySharedUsers", h.roomserverURL+RoomserverQuerySharedUsersPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryKnownUsers(
ctx context.Context,
request *api.QueryKnownUsersRequest,
response *api.QueryKnownUsersResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryKnownUsers", h.roomserverURL+RoomserverQueryKnownUsersPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryAuthChain(
ctx context.Context,
request *api.QueryAuthChainRequest,
response *api.QueryAuthChainResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryAuthChain", h.roomserverURL+RoomserverQueryAuthChainPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryServerBannedFromRoom(
ctx context.Context,
request *api.QueryServerBannedFromRoomRequest,
response *api.QueryServerBannedFromRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryServerBannedFromRoom", h.roomserverURL+RoomserverQueryServerBannedFromRoomPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryRestrictedJoinAllowed(
ctx context.Context,
request *api.QueryRestrictedJoinAllowedRequest,
response *api.QueryRestrictedJoinAllowedResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryRestrictedJoinAllowed", h.roomserverURL+RoomserverQueryRestrictedJoinAllowed,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformForget(
ctx context.Context,
request *api.PerformForgetRequest,
response *api.PerformForgetResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformForget", h.roomserverURL+RoomserverPerformForgetPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryMembershipAtEvent(ctx context.Context, request *api.QueryMembershipAtEventRequest, response *api.QueryMembershipAtEventResponse) error {
return httputil.CallInternalRPCAPI(
"QueryMembershiptAtEvent", h.roomserverURL+RoomserverQueryMembershipAtEventPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryLeftUsers(ctx context.Context, request *api.QueryLeftUsersRequest, response *api.QueryLeftUsersResponse) error {
return httputil.CallInternalRPCAPI(
"RoomserverQueryLeftMembers", h.roomserverURL+RoomserverQueryLeftMembersPath,
h.httpClient, ctx, request, response,
)
}

View file

@ -1,216 +0,0 @@
package inthttp
import (
"github.com/gorilla/mux"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/roomserver/api"
)
// AddRoutes adds the RoomserverInternalAPI handlers to the http.ServeMux.
// nolint: gocyclo
func AddRoutes(r api.RoomserverInternalAPI, internalAPIMux *mux.Router, enableMetrics bool) {
internalAPIMux.Handle(
RoomserverInputRoomEventsPath,
httputil.MakeInternalRPCAPI("RoomserverInputRoomEvents", enableMetrics, r.InputRoomEvents),
)
internalAPIMux.Handle(
RoomserverPerformInvitePath,
httputil.MakeInternalRPCAPI("RoomserverPerformInvite", enableMetrics, r.PerformInvite),
)
internalAPIMux.Handle(
RoomserverPerformJoinPath,
httputil.MakeInternalRPCAPI("RoomserverPerformJoin", enableMetrics, r.PerformJoin),
)
internalAPIMux.Handle(
RoomserverPerformLeavePath,
httputil.MakeInternalRPCAPI("RoomserverPerformLeave", enableMetrics, r.PerformLeave),
)
internalAPIMux.Handle(
RoomserverPerformPeekPath,
httputil.MakeInternalRPCAPI("RoomserverPerformPeek", enableMetrics, r.PerformPeek),
)
internalAPIMux.Handle(
RoomserverPerformInboundPeekPath,
httputil.MakeInternalRPCAPI("RoomserverPerformInboundPeek", enableMetrics, r.PerformInboundPeek),
)
internalAPIMux.Handle(
RoomserverPerformUnpeekPath,
httputil.MakeInternalRPCAPI("RoomserverPerformUnpeek", enableMetrics, r.PerformUnpeek),
)
internalAPIMux.Handle(
RoomserverPerformRoomUpgradePath,
httputil.MakeInternalRPCAPI("RoomserverPerformRoomUpgrade", enableMetrics, r.PerformRoomUpgrade),
)
internalAPIMux.Handle(
RoomserverPerformPublishPath,
httputil.MakeInternalRPCAPI("RoomserverPerformPublish", enableMetrics, r.PerformPublish),
)
internalAPIMux.Handle(
RoomserverPerformAdminEvacuateRoomPath,
httputil.MakeInternalRPCAPI("RoomserverPerformAdminEvacuateRoom", enableMetrics, r.PerformAdminEvacuateRoom),
)
internalAPIMux.Handle(
RoomserverPerformAdminEvacuateUserPath,
httputil.MakeInternalRPCAPI("RoomserverPerformAdminEvacuateUser", enableMetrics, r.PerformAdminEvacuateUser),
)
internalAPIMux.Handle(
RoomserverPerformAdminPurgeRoomPath,
httputil.MakeInternalRPCAPI("RoomserverPerformAdminPurgeRoom", enableMetrics, r.PerformAdminPurgeRoom),
)
internalAPIMux.Handle(
RoomserverPerformAdminDownloadStatePath,
httputil.MakeInternalRPCAPI("RoomserverPerformAdminDownloadState", enableMetrics, r.PerformAdminDownloadState),
)
internalAPIMux.Handle(
RoomserverQueryPublishedRoomsPath,
httputil.MakeInternalRPCAPI("RoomserverQueryPublishedRooms", enableMetrics, r.QueryPublishedRooms),
)
internalAPIMux.Handle(
RoomserverQueryLatestEventsAndStatePath,
httputil.MakeInternalRPCAPI("RoomserverQueryLatestEventsAndState", enableMetrics, r.QueryLatestEventsAndState),
)
internalAPIMux.Handle(
RoomserverQueryStateAfterEventsPath,
httputil.MakeInternalRPCAPI("RoomserverQueryStateAfterEvents", enableMetrics, r.QueryStateAfterEvents),
)
internalAPIMux.Handle(
RoomserverQueryEventsByIDPath,
httputil.MakeInternalRPCAPI("RoomserverQueryEventsByID", enableMetrics, r.QueryEventsByID),
)
internalAPIMux.Handle(
RoomserverQueryMembershipForUserPath,
httputil.MakeInternalRPCAPI("RoomserverQueryMembershipForUser", enableMetrics, r.QueryMembershipForUser),
)
internalAPIMux.Handle(
RoomserverQueryMembershipsForRoomPath,
httputil.MakeInternalRPCAPI("RoomserverQueryMembershipsForRoom", enableMetrics, r.QueryMembershipsForRoom),
)
internalAPIMux.Handle(
RoomserverQueryServerJoinedToRoomPath,
httputil.MakeInternalRPCAPI("RoomserverQueryServerJoinedToRoom", enableMetrics, r.QueryServerJoinedToRoom),
)
internalAPIMux.Handle(
RoomserverQueryServerAllowedToSeeEventPath,
httputil.MakeInternalRPCAPI("RoomserverQueryServerAllowedToSeeEvent", enableMetrics, r.QueryServerAllowedToSeeEvent),
)
internalAPIMux.Handle(
RoomserverQueryMissingEventsPath,
httputil.MakeInternalRPCAPI("RoomserverQueryMissingEvents", enableMetrics, r.QueryMissingEvents),
)
internalAPIMux.Handle(
RoomserverQueryStateAndAuthChainPath,
httputil.MakeInternalRPCAPI("RoomserverQueryStateAndAuthChain", enableMetrics, r.QueryStateAndAuthChain),
)
internalAPIMux.Handle(
RoomserverPerformBackfillPath,
httputil.MakeInternalRPCAPI("RoomserverPerformBackfill", enableMetrics, r.PerformBackfill),
)
internalAPIMux.Handle(
RoomserverPerformForgetPath,
httputil.MakeInternalRPCAPI("RoomserverPerformForget", enableMetrics, r.PerformForget),
)
internalAPIMux.Handle(
RoomserverQueryRoomVersionCapabilitiesPath,
httputil.MakeInternalRPCAPI("RoomserverQueryRoomVersionCapabilities", enableMetrics, r.QueryRoomVersionCapabilities),
)
internalAPIMux.Handle(
RoomserverQueryRoomVersionForRoomPath,
httputil.MakeInternalRPCAPI("RoomserverQueryRoomVersionForRoom", enableMetrics, r.QueryRoomVersionForRoom),
)
internalAPIMux.Handle(
RoomserverSetRoomAliasPath,
httputil.MakeInternalRPCAPI("RoomserverSetRoomAlias", enableMetrics, r.SetRoomAlias),
)
internalAPIMux.Handle(
RoomserverGetRoomIDForAliasPath,
httputil.MakeInternalRPCAPI("RoomserverGetRoomIDForAlias", enableMetrics, r.GetRoomIDForAlias),
)
internalAPIMux.Handle(
RoomserverGetAliasesForRoomIDPath,
httputil.MakeInternalRPCAPI("RoomserverGetAliasesForRoomID", enableMetrics, r.GetAliasesForRoomID),
)
internalAPIMux.Handle(
RoomserverRemoveRoomAliasPath,
httputil.MakeInternalRPCAPI("RoomserverRemoveRoomAlias", enableMetrics, r.RemoveRoomAlias),
)
internalAPIMux.Handle(
RoomserverQueryCurrentStatePath,
httputil.MakeInternalRPCAPI("RoomserverQueryCurrentState", enableMetrics, r.QueryCurrentState),
)
internalAPIMux.Handle(
RoomserverQueryRoomsForUserPath,
httputil.MakeInternalRPCAPI("RoomserverQueryRoomsForUser", enableMetrics, r.QueryRoomsForUser),
)
internalAPIMux.Handle(
RoomserverQueryBulkStateContentPath,
httputil.MakeInternalRPCAPI("RoomserverQueryBulkStateContent", enableMetrics, r.QueryBulkStateContent),
)
internalAPIMux.Handle(
RoomserverQuerySharedUsersPath,
httputil.MakeInternalRPCAPI("RoomserverQuerySharedUsers", enableMetrics, r.QuerySharedUsers),
)
internalAPIMux.Handle(
RoomserverQueryKnownUsersPath,
httputil.MakeInternalRPCAPI("RoomserverQueryKnownUsers", enableMetrics, r.QueryKnownUsers),
)
internalAPIMux.Handle(
RoomserverQueryServerBannedFromRoomPath,
httputil.MakeInternalRPCAPI("RoomserverQueryServerBannedFromRoom", enableMetrics, r.QueryServerBannedFromRoom),
)
internalAPIMux.Handle(
RoomserverQueryAuthChainPath,
httputil.MakeInternalRPCAPI("RoomserverQueryAuthChain", enableMetrics, r.QueryAuthChain),
)
internalAPIMux.Handle(
RoomserverQueryRestrictedJoinAllowed,
httputil.MakeInternalRPCAPI("RoomserverQueryRestrictedJoinAllowed", enableMetrics, r.QueryRestrictedJoinAllowed),
)
internalAPIMux.Handle(
RoomserverQueryMembershipAtEventPath,
httputil.MakeInternalRPCAPI("RoomserverQueryMembershipAtEventPath", enableMetrics, r.QueryMembershipAtEvent),
)
internalAPIMux.Handle(
RoomserverQueryLeftMembersPath,
httputil.MakeInternalRPCAPI("RoomserverQueryLeftMembersPath", enableMetrics, r.QueryLeftUsers),
)
}

View file

@ -15,22 +15,14 @@
package roomserver package roomserver
import ( import (
"github.com/gorilla/mux"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/internal" "github.com/matrix-org/dendrite/roomserver/internal"
"github.com/matrix-org/dendrite/roomserver/inthttp"
"github.com/matrix-org/dendrite/roomserver/storage" "github.com/matrix-org/dendrite/roomserver/storage"
"github.com/matrix-org/dendrite/setup/base" "github.com/matrix-org/dendrite/setup/base"
) )
// AddInternalRoutes registers HTTP handlers for the internal API. Invokes functions
// on the given input API.
func AddInternalRoutes(router *mux.Router, intAPI api.RoomserverInternalAPI, enableMetrics bool) {
inthttp.AddRoutes(intAPI, router, enableMetrics)
}
// NewInternalAPI returns a concerete implementation of the internal API. Callers // NewInternalAPI returns a concerete implementation of the internal API. Callers
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes. // can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
func NewInternalAPI( func NewInternalAPI(

View file

@ -2,13 +2,10 @@ package roomserver_test
import ( import (
"context" "context"
"net/http"
"reflect" "reflect"
"testing" "testing"
"time" "time"
"github.com/gorilla/mux"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/setup/base" "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/userapi" "github.com/matrix-org/dendrite/userapi"
@ -22,7 +19,6 @@ import (
"github.com/matrix-org/dendrite/roomserver" "github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/inthttp"
"github.com/matrix-org/dendrite/roomserver/storage" "github.com/matrix-org/dendrite/roomserver/storage"
"github.com/matrix-org/dendrite/test" "github.com/matrix-org/dendrite/test"
"github.com/matrix-org/dendrite/test/testrig" "github.com/matrix-org/dendrite/test/testrig"
@ -207,24 +203,7 @@ func Test_QueryLeftUsers(t *testing.T) {
} }
} }
t.Run("HTTP API", func(t *testing.T) { testCase(rsAPI)
router := mux.NewRouter().PathPrefix(httputil.InternalPathPrefix).Subrouter()
roomserver.AddInternalRoutes(router, rsAPI, false)
apiURL, cancel := test.ListenAndServe(t, router, false)
defer cancel()
httpAPI, err := inthttp.NewRoomserverClient(apiURL, &http.Client{Timeout: time.Second * 5}, nil)
if err != nil {
t.Fatalf("failed to create HTTP client")
}
testCase(httpAPI)
})
t.Run("Monolith", func(t *testing.T) {
testCase(rsAPI)
// also test tracing
traceAPI := &api.RoomserverInternalAPITrace{Impl: rsAPI}
testCase(traceAPI)
})
}) })
} }

View file

@ -17,7 +17,6 @@ package base
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/tls"
"database/sql" "database/sql"
"embed" "embed"
"encoding/json" "encoding/json"
@ -38,8 +37,6 @@ import (
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"go.uber.org/atomic" "go.uber.org/atomic"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"github.com/matrix-org/dendrite/internal" "github.com/matrix-org/dendrite/internal"
"github.com/matrix-org/dendrite/internal/caching" "github.com/matrix-org/dendrite/internal/caching"
@ -53,19 +50,9 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
asinthttp "github.com/matrix-org/dendrite/appservice/inthttp"
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
federationIntHTTP "github.com/matrix-org/dendrite/federationapi/inthttp"
keyserverAPI "github.com/matrix-org/dendrite/keyserver/api"
keyinthttp "github.com/matrix-org/dendrite/keyserver/inthttp"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
rsinthttp "github.com/matrix-org/dendrite/roomserver/inthttp"
"github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/setup/jetstream" "github.com/matrix-org/dendrite/setup/jetstream"
"github.com/matrix-org/dendrite/setup/process" "github.com/matrix-org/dendrite/setup/process"
userapi "github.com/matrix-org/dendrite/userapi/api"
userapiinthttp "github.com/matrix-org/dendrite/userapi/inthttp"
) )
//go:embed static/*.gotmpl //go:embed static/*.gotmpl
@ -78,7 +65,6 @@ var staticContent embed.FS
// Must be closed when shutting down. // Must be closed when shutting down.
type BaseDendrite struct { type BaseDendrite struct {
*process.ProcessContext *process.ProcessContext
componentName string
tracerCloser io.Closer tracerCloser io.Closer
PublicClientAPIMux *mux.Router PublicClientAPIMux *mux.Router
PublicFederationAPIMux *mux.Router PublicFederationAPIMux *mux.Router
@ -86,12 +72,9 @@ type BaseDendrite struct {
PublicMediaAPIMux *mux.Router PublicMediaAPIMux *mux.Router
PublicWellKnownAPIMux *mux.Router PublicWellKnownAPIMux *mux.Router
PublicStaticMux *mux.Router PublicStaticMux *mux.Router
InternalAPIMux *mux.Router
DendriteAdminMux *mux.Router DendriteAdminMux *mux.Router
SynapseAdminMux *mux.Router SynapseAdminMux *mux.Router
NATS *jetstream.NATSInstance NATS *jetstream.NATSInstance
UseHTTPAPIs bool
apiHttpClient *http.Client
Cfg *config.Dendrite Cfg *config.Dendrite
Caches *caching.Caches Caches *caching.Caches
DNSCache *gomatrixserverlib.DNSCache DNSCache *gomatrixserverlib.DNSCache
@ -105,38 +88,26 @@ type BaseDendrite struct {
const NoListener = "" const NoListener = ""
const HTTPServerTimeout = time.Minute * 5 const HTTPServerTimeout = time.Minute * 5
const HTTPClientTimeout = time.Second * 30
type BaseDendriteOptions int type BaseDendriteOptions int
const ( const (
DisableMetrics BaseDendriteOptions = iota DisableMetrics BaseDendriteOptions = iota
UseHTTPAPIs
PolylithMode
) )
// NewBaseDendrite creates a new instance to be used by a component. // NewBaseDendrite creates a new instance to be used by a component.
// The componentName is used for logging purposes, and should be a friendly name func NewBaseDendrite(cfg *config.Dendrite, options ...BaseDendriteOptions) *BaseDendrite {
// of the compontent running, e.g. "SyncAPI"
func NewBaseDendrite(cfg *config.Dendrite, componentName string, options ...BaseDendriteOptions) *BaseDendrite {
platformSanityChecks() platformSanityChecks()
useHTTPAPIs := false
enableMetrics := true enableMetrics := true
isMonolith := true
for _, opt := range options { for _, opt := range options {
switch opt { switch opt {
case DisableMetrics: case DisableMetrics:
enableMetrics = false enableMetrics = false
case UseHTTPAPIs:
useHTTPAPIs = true
case PolylithMode:
isMonolith = false
useHTTPAPIs = true
} }
} }
configErrors := &config.ConfigErrors{} configErrors := &config.ConfigErrors{}
cfg.Verify(configErrors, isMonolith) cfg.Verify(configErrors)
if len(*configErrors) > 0 { if len(*configErrors) > 0 {
for _, err := range *configErrors { for _, err := range *configErrors {
logrus.Errorf("Configuration error: %s", err) logrus.Errorf("Configuration error: %s", err)
@ -145,7 +116,7 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, options ...Base
} }
internal.SetupStdLogging() internal.SetupStdLogging()
internal.SetupHookLogging(cfg.Logging, componentName) internal.SetupHookLogging(cfg.Logging)
internal.SetupPprof() internal.SetupPprof()
logrus.Infof("Dendrite version %s", internal.VersionString()) logrus.Infof("Dendrite version %s", internal.VersionString())
@ -154,14 +125,13 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, options ...Base
logrus.Warn("Open registration is enabled") logrus.Warn("Open registration is enabled")
} }
closer, err := cfg.SetupTracing("Dendrite" + componentName) closer, err := cfg.SetupTracing()
if err != nil { if err != nil {
logrus.WithError(err).Panicf("failed to start opentracing") logrus.WithError(err).Panicf("failed to start opentracing")
} }
var fts *fulltext.Search var fts *fulltext.Search
isSyncOrMonolith := componentName == "syncapi" || isMonolith if cfg.SyncAPI.Fulltext.Enabled {
if cfg.SyncAPI.Fulltext.Enabled && isSyncOrMonolith {
fts, err = fulltext.New(cfg.SyncAPI.Fulltext) fts, err = fulltext.New(cfg.SyncAPI.Fulltext)
if err != nil { if err != nil {
logrus.WithError(err).Panicf("failed to create full text") logrus.WithError(err).Panicf("failed to create full text")
@ -196,32 +166,12 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, options ...Base
) )
} }
apiClient := http.Client{
Timeout: time.Minute * 10,
Transport: &http2.Transport{
AllowHTTP: true,
DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) {
// Ordinarily HTTP/2 would expect TLS, but the remote listener is
// H2C-enabled (HTTP/2 without encryption). Overriding the DialTLS
// function with a plain Dial allows us to trick the HTTP client
// into establishing a HTTP/2 connection without TLS.
// TODO: Eventually we will want to look at authenticating and
// encrypting these internal HTTP APIs, at which point we will have
// to reconsider H2C and change all this anyway.
return net.Dial(network, addr)
},
},
}
// If we're in monolith mode, we'll set up a global pool of database // If we're in monolith mode, we'll set up a global pool of database
// connections. A component is welcome to use this pool if they don't // connections. A component is welcome to use this pool if they don't
// have a separate database config of their own. // have a separate database config of their own.
var db *sql.DB var db *sql.DB
var writer sqlutil.Writer var writer sqlutil.Writer
if cfg.Global.DatabaseOptions.ConnectionString != "" { if cfg.Global.DatabaseOptions.ConnectionString != "" {
if !isMonolith {
logrus.Panic("Using a global database connection pool is not supported in polylith deployments")
}
if cfg.Global.DatabaseOptions.ConnectionString.IsSQLite() { if cfg.Global.DatabaseOptions.ConnectionString.IsSQLite() {
logrus.Panic("Using a global database connection pool is not supported with SQLite databases") logrus.Panic("Using a global database connection pool is not supported with SQLite databases")
} }
@ -246,8 +196,6 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, options ...Base
return &BaseDendrite{ return &BaseDendrite{
ProcessContext: process.NewProcessContext(), ProcessContext: process.NewProcessContext(),
componentName: componentName,
UseHTTPAPIs: useHTTPAPIs,
tracerCloser: closer, tracerCloser: closer,
Cfg: cfg, Cfg: cfg,
Caches: caching.NewRistrettoCache(cfg.Global.Cache.EstimatedMaxSize, cfg.Global.Cache.MaxAge, enableMetrics), Caches: caching.NewRistrettoCache(cfg.Global.Cache.EstimatedMaxSize, cfg.Global.Cache.MaxAge, enableMetrics),
@ -258,11 +206,9 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, options ...Base
PublicMediaAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicMediaPathPrefix).Subrouter().UseEncodedPath(), PublicMediaAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicMediaPathPrefix).Subrouter().UseEncodedPath(),
PublicWellKnownAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicWellKnownPrefix).Subrouter().UseEncodedPath(), PublicWellKnownAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicWellKnownPrefix).Subrouter().UseEncodedPath(),
PublicStaticMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicStaticPath).Subrouter().UseEncodedPath(), PublicStaticMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicStaticPath).Subrouter().UseEncodedPath(),
InternalAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.InternalPathPrefix).Subrouter().UseEncodedPath(),
DendriteAdminMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.DendriteAdminPathPrefix).Subrouter().UseEncodedPath(), DendriteAdminMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.DendriteAdminPathPrefix).Subrouter().UseEncodedPath(),
SynapseAdminMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.SynapseAdminPathPrefix).Subrouter().UseEncodedPath(), SynapseAdminMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.SynapseAdminPathPrefix).Subrouter().UseEncodedPath(),
NATS: &jetstream.NATSInstance{}, NATS: &jetstream.NATSInstance{},
apiHttpClient: &apiClient,
Database: db, // set if monolith with global connection pool only Database: db, // set if monolith with global connection pool only
DatabaseWriter: writer, // set if monolith with global connection pool only DatabaseWriter: writer, // set if monolith with global connection pool only
EnableMetrics: enableMetrics, EnableMetrics: enableMetrics,
@ -300,52 +246,6 @@ func (b *BaseDendrite) DatabaseConnection(dbProperties *config.DatabaseOptions,
return nil, nil, fmt.Errorf("no database connections configured") return nil, nil, fmt.Errorf("no database connections configured")
} }
// AppserviceHTTPClient returns the AppServiceInternalAPI for hitting the appservice component over HTTP.
func (b *BaseDendrite) AppserviceHTTPClient() appserviceAPI.AppServiceInternalAPI {
a, err := asinthttp.NewAppserviceClient(b.Cfg.AppServiceURL(), b.apiHttpClient)
if err != nil {
logrus.WithError(err).Panic("CreateHTTPAppServiceAPIs failed")
}
return a
}
// RoomserverHTTPClient returns RoomserverInternalAPI for hitting the roomserver over HTTP.
func (b *BaseDendrite) RoomserverHTTPClient() roomserverAPI.RoomserverInternalAPI {
rsAPI, err := rsinthttp.NewRoomserverClient(b.Cfg.RoomServerURL(), b.apiHttpClient, b.Caches)
if err != nil {
logrus.WithError(err).Panic("RoomserverHTTPClient failed", b.apiHttpClient)
}
return rsAPI
}
// UserAPIClient returns UserInternalAPI for hitting the userapi over HTTP.
func (b *BaseDendrite) UserAPIClient() userapi.UserInternalAPI {
userAPI, err := userapiinthttp.NewUserAPIClient(b.Cfg.UserAPIURL(), b.apiHttpClient)
if err != nil {
logrus.WithError(err).Panic("UserAPIClient failed", b.apiHttpClient)
}
return userAPI
}
// FederationAPIHTTPClient returns FederationInternalAPI for hitting
// the federation API server over HTTP
func (b *BaseDendrite) FederationAPIHTTPClient() federationAPI.FederationInternalAPI {
f, err := federationIntHTTP.NewFederationAPIClient(b.Cfg.FederationAPIURL(), b.apiHttpClient, b.Caches)
if err != nil {
logrus.WithError(err).Panic("FederationAPIHTTPClient failed", b.apiHttpClient)
}
return f
}
// KeyServerHTTPClient returns KeyInternalAPI for hitting the key server over HTTP
func (b *BaseDendrite) KeyServerHTTPClient() keyserverAPI.KeyInternalAPI {
f, err := keyinthttp.NewKeyServerClient(b.Cfg.KeyServerURL(), b.apiHttpClient)
if err != nil {
logrus.WithError(err).Panic("KeyServerHTTPClient failed", b.apiHttpClient)
}
return f
}
// PushGatewayHTTPClient returns a new client for interacting with (external) Push Gateways. // PushGatewayHTTPClient returns a new client for interacting with (external) Push Gateways.
func (b *BaseDendrite) PushGatewayHTTPClient() pushgateway.Client { func (b *BaseDendrite) PushGatewayHTTPClient() pushgateway.Client {
return pushgateway.NewHTTPClient(b.Cfg.UserAPI.PushGatewayDisableTLSValidation) return pushgateway.NewHTTPClient(b.Cfg.UserAPI.PushGatewayDisableTLSValidation)
@ -442,20 +342,18 @@ func (b *BaseDendrite) ConfigureAdminEndpoints() {
}) })
} }
// SetupAndServeHTTP sets up the HTTP server to serve endpoints registered on // SetupAndServeHTTP sets up the HTTP server to serve client & federation APIs
// ApiMux under /api/ and adds a prometheus handler under /metrics. // and adds a prometheus handler under /_dendrite/metrics.
func (b *BaseDendrite) SetupAndServeHTTP( func (b *BaseDendrite) SetupAndServeHTTP(
internalHTTPAddr, externalHTTPAddr config.HTTPAddress, externalHTTPAddr config.HTTPAddress,
certFile, keyFile *string, certFile, keyFile *string,
) { ) {
// Manually unlocked right before actually serving requests, // Manually unlocked right before actually serving requests,
// as we don't return from this method (defer doesn't work). // as we don't return from this method (defer doesn't work).
b.startupLock.Lock() b.startupLock.Lock()
internalAddr, _ := internalHTTPAddr.Address()
externalAddr, _ := externalHTTPAddr.Address() externalAddr, _ := externalHTTPAddr.Address()
externalRouter := mux.NewRouter().SkipClean(true).UseEncodedPath() externalRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
internalRouter := externalRouter
externalServ := &http.Server{ externalServ := &http.Server{
Addr: string(externalAddr), Addr: string(externalAddr),
@ -465,25 +363,6 @@ func (b *BaseDendrite) SetupAndServeHTTP(
return b.ProcessContext.Context() return b.ProcessContext.Context()
}, },
} }
internalServ := externalServ
if internalAddr != NoListener && externalAddr != internalAddr {
// H2C allows us to accept HTTP/2 connections without TLS
// encryption. Since we don't currently require any form of
// authentication or encryption on these internal HTTP APIs,
// H2C gives us all of the advantages of HTTP/2 (such as
// stream multiplexing and avoiding head-of-line blocking)
// without enabling TLS.
internalH2S := &http2.Server{}
internalRouter = mux.NewRouter().SkipClean(true).UseEncodedPath()
internalServ = &http.Server{
Addr: string(internalAddr),
Handler: h2c.NewHandler(internalRouter, internalH2S),
BaseContext: func(_ net.Listener) context.Context {
return b.ProcessContext.Context()
},
}
}
b.configureHTTPErrors() b.configureHTTPErrors()
@ -492,9 +371,8 @@ func (b *BaseDendrite) SetupAndServeHTTP(
http.Redirect(w, r, httputil.PublicStaticPath, http.StatusFound) http.Redirect(w, r, httputil.PublicStaticPath, http.StatusFound)
}) })
internalRouter.PathPrefix(httputil.InternalPathPrefix).Handler(b.InternalAPIMux)
if b.Cfg.Global.Metrics.Enabled { if b.Cfg.Global.Metrics.Enabled {
internalRouter.Handle("/metrics", httputil.WrapHandlerInBasicAuth(promhttp.Handler(), b.Cfg.Global.Metrics.BasicAuth)) externalRouter.Handle("/metrics", httputil.WrapHandlerInBasicAuth(promhttp.Handler(), b.Cfg.Global.Metrics.BasicAuth))
} }
b.ConfigureAdminEndpoints() b.ConfigureAdminEndpoints()
@ -528,7 +406,7 @@ func (b *BaseDendrite) SetupAndServeHTTP(
}) })
federationHandler = sentryHandler.Handle(b.PublicFederationAPIMux) federationHandler = sentryHandler.Handle(b.PublicFederationAPIMux)
} }
internalRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(b.DendriteAdminMux) externalRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(b.DendriteAdminMux)
externalRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(clientHandler) externalRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(clientHandler)
if !b.Cfg.Global.DisableFederation { if !b.Cfg.Global.DisableFederation {
externalRouter.PathPrefix(httputil.PublicKeyPathPrefix).Handler(b.PublicKeyAPIMux) externalRouter.PathPrefix(httputil.PublicKeyPathPrefix).Handler(b.PublicKeyAPIMux)
@ -540,38 +418,11 @@ func (b *BaseDendrite) SetupAndServeHTTP(
externalRouter.PathPrefix(httputil.PublicStaticPath).Handler(b.PublicStaticMux) externalRouter.PathPrefix(httputil.PublicStaticPath).Handler(b.PublicStaticMux)
b.startupLock.Unlock() b.startupLock.Unlock()
if internalAddr != NoListener && internalAddr != externalAddr {
go func() {
var internalShutdown atomic.Bool // RegisterOnShutdown can be called more than once
logrus.Infof("Starting internal %s listener on %s", b.componentName, internalServ.Addr)
b.ProcessContext.ComponentStarted()
internalServ.RegisterOnShutdown(func() {
if internalShutdown.CompareAndSwap(false, true) {
b.ProcessContext.ComponentFinished()
logrus.Infof("Stopped internal HTTP listener")
}
})
if certFile != nil && keyFile != nil {
if err := internalServ.ListenAndServeTLS(*certFile, *keyFile); err != nil {
if err != http.ErrServerClosed {
logrus.WithError(err).Fatal("failed to serve HTTPS")
}
}
} else {
if err := internalServ.ListenAndServe(); err != nil {
if err != http.ErrServerClosed {
logrus.WithError(err).Fatal("failed to serve HTTP")
}
}
}
logrus.Infof("Stopped internal %s listener on %s", b.componentName, internalServ.Addr)
}()
}
if externalAddr != NoListener { if externalAddr != NoListener {
go func() { go func() {
var externalShutdown atomic.Bool // RegisterOnShutdown can be called more than once var externalShutdown atomic.Bool // RegisterOnShutdown can be called more than once
logrus.Infof("Starting external %s listener on %s", b.componentName, externalServ.Addr) logrus.Infof("Starting external listener on %s", externalServ.Addr)
b.ProcessContext.ComponentStarted() b.ProcessContext.ComponentStarted()
externalServ.RegisterOnShutdown(func() { externalServ.RegisterOnShutdown(func() {
if externalShutdown.CompareAndSwap(false, true) { if externalShutdown.CompareAndSwap(false, true) {
@ -592,7 +443,7 @@ func (b *BaseDendrite) SetupAndServeHTTP(
} }
} }
} }
logrus.Infof("Stopped external %s listener on %s", b.componentName, externalServ.Addr) logrus.Infof("Stopped external listener on %s", externalServ.Addr)
}() }()
} }
@ -600,7 +451,6 @@ func (b *BaseDendrite) SetupAndServeHTTP(
<-b.ProcessContext.WaitForShutdown() <-b.ProcessContext.WaitForShutdown()
logrus.Infof("Stopping HTTP listeners") logrus.Infof("Stopping HTTP listeners")
_ = internalServ.Shutdown(context.Background())
_ = externalServ.Shutdown(context.Background()) _ = externalServ.Shutdown(context.Background())
logrus.Infof("Stopped HTTP listeners") logrus.Infof("Stopped HTTP listeners")
} }

View file

@ -35,7 +35,7 @@ func TestLandingPage(t *testing.T) {
s.Close() s.Close()
// start base with the listener and wait for it to be started // start base with the listener and wait for it to be started
go b.SetupAndServeHTTP("", config.HTTPAddress(s.URL), nil, nil) go b.SetupAndServeHTTP(config.HTTPAddress(s.URL), nil, nil)
time.Sleep(time.Millisecond * 10) time.Sleep(time.Millisecond * 10)
// When hitting /, we should be redirected to /_matrix/static, which should contain the landing page // When hitting /, we should be redirected to /_matrix/static, which should contain the landing page

View file

@ -79,8 +79,6 @@ type Dendrite struct {
// Any information derived from the configuration options for later use. // Any information derived from the configuration options for later use.
Derived Derived `yaml:"-"` Derived Derived `yaml:"-"`
IsMonolith bool `yaml:"-"`
} }
// TODO: Kill Derived // TODO: Kill Derived
@ -114,15 +112,6 @@ type Derived struct {
// servers from creating RoomIDs in exclusive application service namespaces // servers from creating RoomIDs in exclusive application service namespaces
} }
type InternalAPIOptions struct {
Listen HTTPAddress `yaml:"listen"`
Connect HTTPAddress `yaml:"connect"`
}
type ExternalAPIOptions struct {
Listen HTTPAddress `yaml:"listen"`
}
// A Path on the filesystem. // A Path on the filesystem.
type Path string type Path string
@ -191,7 +180,7 @@ type ConfigErrors []string
// Load a yaml config file for a server run as multiple processes or as a monolith. // Load a yaml config file for a server run as multiple processes or as a monolith.
// Checks the config to ensure that it is valid. // Checks the config to ensure that it is valid.
func Load(configPath string, monolith bool) (*Dendrite, error) { func Load(configPath string) (*Dendrite, error) {
configData, err := os.ReadFile(configPath) configData, err := os.ReadFile(configPath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -202,28 +191,26 @@ func Load(configPath string, monolith bool) (*Dendrite, error) {
} }
// Pass the current working directory and os.ReadFile so that they can // Pass the current working directory and os.ReadFile so that they can
// be mocked in the tests // be mocked in the tests
return loadConfig(basePath, configData, os.ReadFile, monolith) return loadConfig(basePath, configData, os.ReadFile)
} }
func loadConfig( func loadConfig(
basePath string, basePath string,
configData []byte, configData []byte,
readFile func(string) ([]byte, error), readFile func(string) ([]byte, error),
monolithic bool,
) (*Dendrite, error) { ) (*Dendrite, error) {
var c Dendrite var c Dendrite
c.Defaults(DefaultOpts{ c.Defaults(DefaultOpts{
Generate: false, Generate: false,
Monolithic: monolithic, SingleDatabase: true,
}) })
c.IsMonolith = monolithic
var err error var err error
if err = yaml.Unmarshal(configData, &c); err != nil { if err = yaml.Unmarshal(configData, &c); err != nil {
return nil, err return nil, err
} }
if err = c.check(monolithic); err != nil { if err = c.check(); err != nil {
return nil, err return nil, err
} }
@ -333,8 +320,8 @@ func (config *Dendrite) Derive() error {
} }
type DefaultOpts struct { type DefaultOpts struct {
Generate bool Generate bool
Monolithic bool SingleDatabase bool
} }
// SetDefaults sets default config values if they are not explicitly set. // SetDefaults sets default config values if they are not explicitly set.
@ -355,9 +342,9 @@ func (c *Dendrite) Defaults(opts DefaultOpts) {
c.Wiring() c.Wiring()
} }
func (c *Dendrite) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *Dendrite) Verify(configErrs *ConfigErrors) {
type verifiable interface { type verifiable interface {
Verify(configErrs *ConfigErrors, isMonolith bool) Verify(configErrs *ConfigErrors)
} }
for _, c := range []verifiable{ for _, c := range []verifiable{
&c.Global, &c.ClientAPI, &c.FederationAPI, &c.Global, &c.ClientAPI, &c.FederationAPI,
@ -365,7 +352,7 @@ func (c *Dendrite) Verify(configErrs *ConfigErrors, isMonolith bool) {
&c.SyncAPI, &c.UserAPI, &c.SyncAPI, &c.UserAPI,
&c.AppServiceAPI, &c.RelayAPI, &c.MSCs, &c.AppServiceAPI, &c.RelayAPI, &c.MSCs,
} { } {
c.Verify(configErrs, isMonolith) c.Verify(configErrs)
} }
} }
@ -415,14 +402,6 @@ func checkNotEmpty(configErrs *ConfigErrors, key, value string) {
} }
} }
// checkNotZero verifies the given value is not zero in the configuration.
// If it is, adds an error to the list.
func checkNotZero(configErrs *ConfigErrors, key string, value int64) {
if value == 0 {
configErrs.Add(fmt.Sprintf("missing config key %q", key))
}
}
// checkPositive verifies the given value is positive (zero included) // checkPositive verifies the given value is positive (zero included)
// in the configuration. If it is not, adds an error to the list. // in the configuration. If it is not, adds an error to the list.
func checkPositive(configErrs *ConfigErrors, key string, value int64) { func checkPositive(configErrs *ConfigErrors, key string, value int64) {
@ -431,26 +410,6 @@ func checkPositive(configErrs *ConfigErrors, key string, value int64) {
} }
} }
// checkURL verifies that the parameter is a valid URL
func checkURL(configErrs *ConfigErrors, key, value string) {
if value == "" {
configErrs.Add(fmt.Sprintf("missing config key %q", key))
return
}
url, err := url.Parse(value)
if err != nil {
configErrs.Add(fmt.Sprintf("config key %q contains invalid URL (%s)", key, err.Error()))
return
}
switch url.Scheme {
case "http":
case "https":
default:
configErrs.Add(fmt.Sprintf("config key %q URL should be http:// or https://", key))
return
}
}
// checkLogging verifies the parameters logging.* are valid. // checkLogging verifies the parameters logging.* are valid.
func (config *Dendrite) checkLogging(configErrs *ConfigErrors) { func (config *Dendrite) checkLogging(configErrs *ConfigErrors) {
for _, logrusHook := range config.Logging { for _, logrusHook := range config.Logging {
@ -461,7 +420,7 @@ func (config *Dendrite) checkLogging(configErrs *ConfigErrors) {
// check returns an error type containing all errors found within the config // check returns an error type containing all errors found within the config
// file. // file.
func (config *Dendrite) check(_ bool) error { // monolithic func (config *Dendrite) check() error { // monolithic
var configErrs ConfigErrors var configErrs ConfigErrors
if config.Version != Version { if config.Version != Version {
@ -528,58 +487,13 @@ func readKeyPEM(path string, data []byte, enforceKeyIDFormat bool) (gomatrixserv
} }
} }
// AppServiceURL returns a HTTP URL for where the appservice component is listening.
func (config *Dendrite) AppServiceURL() string {
// Hard code the appservice server to talk HTTP for now.
// If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API.
return string(config.AppServiceAPI.InternalAPI.Connect)
}
// FederationAPIURL returns an HTTP URL for where the federation API is listening.
func (config *Dendrite) FederationAPIURL() string {
// Hard code the federationapi to talk HTTP for now.
// If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API.
return string(config.FederationAPI.InternalAPI.Connect)
}
// RoomServerURL returns an HTTP URL for where the roomserver is listening.
func (config *Dendrite) RoomServerURL() string {
// Hard code the roomserver to talk HTTP for now.
// If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API.
return string(config.RoomServer.InternalAPI.Connect)
}
// UserAPIURL returns an HTTP URL for where the userapi is listening.
func (config *Dendrite) UserAPIURL() string {
// Hard code the userapi to talk HTTP for now.
// If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API.
return string(config.UserAPI.InternalAPI.Connect)
}
// KeyServerURL returns an HTTP URL for where the key server is listening.
func (config *Dendrite) KeyServerURL() string {
// Hard code the key server to talk HTTP for now.
// If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API.
return string(config.KeyServer.InternalAPI.Connect)
}
// SetupTracing configures the opentracing using the supplied configuration. // SetupTracing configures the opentracing using the supplied configuration.
func (config *Dendrite) SetupTracing(serviceName string) (closer io.Closer, err error) { func (config *Dendrite) SetupTracing() (closer io.Closer, err error) {
if !config.Tracing.Enabled { if !config.Tracing.Enabled {
return io.NopCloser(bytes.NewReader([]byte{})), nil return io.NopCloser(bytes.NewReader([]byte{})), nil
} }
return config.Tracing.Jaeger.InitGlobalTracer( return config.Tracing.Jaeger.InitGlobalTracer(
serviceName, "Dendrite",
jaegerconfig.Logger(logrusLogger{logrus.StandardLogger()}), jaegerconfig.Logger(logrusLogger{logrus.StandardLogger()}),
jaegerconfig.Metrics(jaegermetrics.NullFactory), jaegerconfig.Metrics(jaegermetrics.NullFactory),
) )

View file

@ -22,15 +22,13 @@ import (
"strings" "strings"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
yaml "gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
type AppServiceAPI struct { type AppServiceAPI struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
Derived *Derived `yaml:"-"` // TODO: Nuke Derived from orbit Derived *Derived `yaml:"-"` // TODO: Nuke Derived from orbit
InternalAPI InternalAPIOptions `yaml:"internal_api,omitempty"`
// DisableTLSValidation disables the validation of X.509 TLS certs // DisableTLSValidation disables the validation of X.509 TLS certs
// on appservice endpoints. This is not recommended in production! // on appservice endpoints. This is not recommended in production!
DisableTLSValidation bool `yaml:"disable_tls_validation"` DisableTLSValidation bool `yaml:"disable_tls_validation"`
@ -39,18 +37,9 @@ type AppServiceAPI struct {
} }
func (c *AppServiceAPI) Defaults(opts DefaultOpts) { func (c *AppServiceAPI) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.InternalAPI.Listen = "http://localhost:7777"
c.InternalAPI.Connect = "http://localhost:7777"
}
} }
func (c *AppServiceAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *AppServiceAPI) Verify(configErrs *ConfigErrors) {
if isMonolith { // polylith required configs below
return
}
checkURL(configErrs, "app_service_api.internal_api.listen", string(c.InternalAPI.Listen))
checkURL(configErrs, "app_service_api.internal_api.connect", string(c.InternalAPI.Connect))
} }
// ApplicationServiceNamespace is the namespace that a specific application // ApplicationServiceNamespace is the namespace that a specific application

View file

@ -9,9 +9,6 @@ type ClientAPI struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
Derived *Derived `yaml:"-"` // TODO: Nuke Derived from orbit Derived *Derived `yaml:"-"` // TODO: Nuke Derived from orbit
InternalAPI InternalAPIOptions `yaml:"internal_api,omitempty"`
ExternalAPI ExternalAPIOptions `yaml:"external_api,omitempty"`
// If set disables new users from registering (except via shared // If set disables new users from registering (except via shared
// secrets) // secrets)
RegistrationDisabled bool `yaml:"registration_disabled"` RegistrationDisabled bool `yaml:"registration_disabled"`
@ -58,11 +55,6 @@ type ClientAPI struct {
} }
func (c *ClientAPI) Defaults(opts DefaultOpts) { func (c *ClientAPI) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.InternalAPI.Listen = "http://localhost:7771"
c.InternalAPI.Connect = "http://localhost:7771"
c.ExternalAPI.Listen = "http://[::]:8071"
}
c.RegistrationSharedSecret = "" c.RegistrationSharedSecret = ""
c.RecaptchaPublicKey = "" c.RecaptchaPublicKey = ""
c.RecaptchaPrivateKey = "" c.RecaptchaPrivateKey = ""
@ -74,7 +66,7 @@ func (c *ClientAPI) Defaults(opts DefaultOpts) {
c.RateLimiting.Defaults() c.RateLimiting.Defaults()
} }
func (c *ClientAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *ClientAPI) Verify(configErrs *ConfigErrors) {
c.TURN.Verify(configErrs) c.TURN.Verify(configErrs)
c.RateLimiting.Verify(configErrs) c.RateLimiting.Verify(configErrs)
if c.RecaptchaEnabled { if c.RecaptchaEnabled {
@ -108,12 +100,6 @@ func (c *ClientAPI) Verify(configErrs *ConfigErrors, isMonolith bool) {
) )
} }
} }
if isMonolith { // polylith required configs below
return
}
checkURL(configErrs, "client_api.internal_api.listen", string(c.InternalAPI.Listen))
checkURL(configErrs, "client_api.internal_api.connect", string(c.InternalAPI.Connect))
checkURL(configErrs, "client_api.external_api.listen", string(c.ExternalAPI.Listen))
} }
type TURN struct { type TURN struct {

View file

@ -1,13 +1,12 @@
package config package config
import "github.com/matrix-org/gomatrixserverlib" import (
"github.com/matrix-org/gomatrixserverlib"
)
type FederationAPI struct { type FederationAPI struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
InternalAPI InternalAPIOptions `yaml:"internal_api,omitempty"`
ExternalAPI ExternalAPIOptions `yaml:"external_api,omitempty"`
// The database stores information used by the federation destination queues to // The database stores information used by the federation destination queues to
// send transactions to remote servers. // send transactions to remote servers.
Database DatabaseOptions `yaml:"database,omitempty"` Database DatabaseOptions `yaml:"database,omitempty"`
@ -42,12 +41,6 @@ type FederationAPI struct {
} }
func (c *FederationAPI) Defaults(opts DefaultOpts) { func (c *FederationAPI) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.InternalAPI.Listen = "http://localhost:7772"
c.InternalAPI.Connect = "http://localhost:7772"
c.ExternalAPI.Listen = "http://[::]:8072"
c.Database.Defaults(10)
}
c.FederationMaxRetries = 16 c.FederationMaxRetries = 16
c.P2PFederationRetriesUntilAssumedOffline = 1 c.P2PFederationRetriesUntilAssumedOffline = 1
c.DisableTLSValidation = false c.DisableTLSValidation = false
@ -68,22 +61,16 @@ func (c *FederationAPI) Defaults(opts DefaultOpts) {
}, },
}, },
} }
if !opts.Monolithic { if !opts.SingleDatabase {
c.Database.ConnectionString = "file:federationapi.db" c.Database.ConnectionString = "file:federationapi.db"
} }
} }
} }
func (c *FederationAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *FederationAPI) Verify(configErrs *ConfigErrors) {
if isMonolith { // polylith required configs below
return
}
if c.Matrix.DatabaseOptions.ConnectionString == "" { if c.Matrix.DatabaseOptions.ConnectionString == "" {
checkNotEmpty(configErrs, "federation_api.database.connection_string", string(c.Database.ConnectionString)) checkNotEmpty(configErrs, "federation_api.database.connection_string", string(c.Database.ConnectionString))
} }
checkURL(configErrs, "federation_api.external_api.listen", string(c.ExternalAPI.Listen))
checkURL(configErrs, "federation_api.internal_api.listen", string(c.InternalAPI.Listen))
checkURL(configErrs, "federation_api.internal_api.connect", string(c.InternalAPI.Connect))
} }
// The config for setting a proxy to use for server->server requests // The config for setting a proxy to use for server->server requests

View file

@ -38,7 +38,6 @@ type Global struct {
// component does not specify any database options of its own, then this pool of // component does not specify any database options of its own, then this pool of
// connections will be used instead. This way we don't have to manage connection // connections will be used instead. This way we don't have to manage connection
// counts on a per-component basis, but can instead do it for the entire monolith. // counts on a per-component basis, but can instead do it for the entire monolith.
// In a polylith deployment, this will be ignored.
DatabaseOptions DatabaseOptions `yaml:"database,omitempty"` DatabaseOptions DatabaseOptions `yaml:"database,omitempty"`
// The server name to delegate server-server communications to, with optional port // The server name to delegate server-server communications to, with optional port
@ -93,7 +92,7 @@ func (c *Global) Defaults(opts DefaultOpts) {
} }
} }
c.KeyValidityPeriod = time.Hour * 24 * 7 c.KeyValidityPeriod = time.Hour * 24 * 7
if opts.Monolithic { if opts.SingleDatabase {
c.DatabaseOptions.Defaults(90) c.DatabaseOptions.Defaults(90)
} }
c.JetStream.Defaults(opts) c.JetStream.Defaults(opts)
@ -105,7 +104,7 @@ func (c *Global) Defaults(opts DefaultOpts) {
c.Cache.Defaults() c.Cache.Defaults()
} }
func (c *Global) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *Global) Verify(configErrs *ConfigErrors) {
checkNotEmpty(configErrs, "global.server_name", string(c.ServerName)) checkNotEmpty(configErrs, "global.server_name", string(c.ServerName))
checkNotEmpty(configErrs, "global.private_key", string(c.PrivateKeyPath)) checkNotEmpty(configErrs, "global.private_key", string(c.PrivateKeyPath))
@ -113,13 +112,13 @@ func (c *Global) Verify(configErrs *ConfigErrors, isMonolith bool) {
v.Verify(configErrs) v.Verify(configErrs)
} }
c.JetStream.Verify(configErrs, isMonolith) c.JetStream.Verify(configErrs)
c.Metrics.Verify(configErrs, isMonolith) c.Metrics.Verify(configErrs)
c.Sentry.Verify(configErrs, isMonolith) c.Sentry.Verify(configErrs)
c.DNSCache.Verify(configErrs, isMonolith) c.DNSCache.Verify(configErrs)
c.ServerNotices.Verify(configErrs, isMonolith) c.ServerNotices.Verify(configErrs)
c.ReportStats.Verify(configErrs, isMonolith) c.ReportStats.Verify(configErrs)
c.Cache.Verify(configErrs, isMonolith) c.Cache.Verify(configErrs)
} }
func (c *Global) IsLocalServerName(serverName gomatrixserverlib.ServerName) bool { func (c *Global) IsLocalServerName(serverName gomatrixserverlib.ServerName) bool {
@ -267,7 +266,7 @@ func (c *Metrics) Defaults(opts DefaultOpts) {
} }
} }
func (c *Metrics) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *Metrics) Verify(configErrs *ConfigErrors) {
} }
// ServerNotices defines the configuration used for sending server notices // ServerNotices defines the configuration used for sending server notices
@ -293,7 +292,7 @@ func (c *ServerNotices) Defaults(opts DefaultOpts) {
} }
} }
func (c *ServerNotices) Verify(errors *ConfigErrors, isMonolith bool) {} func (c *ServerNotices) Verify(errors *ConfigErrors) {}
type Cache struct { type Cache struct {
EstimatedMaxSize DataUnit `yaml:"max_size_estimated"` EstimatedMaxSize DataUnit `yaml:"max_size_estimated"`
@ -305,7 +304,7 @@ func (c *Cache) Defaults() {
c.MaxAge = time.Hour c.MaxAge = time.Hour
} }
func (c *Cache) Verify(errors *ConfigErrors, isMonolith bool) { func (c *Cache) Verify(errors *ConfigErrors) {
checkPositive(errors, "max_size_estimated", int64(c.EstimatedMaxSize)) checkPositive(errors, "max_size_estimated", int64(c.EstimatedMaxSize))
} }
@ -323,7 +322,7 @@ func (c *ReportStats) Defaults() {
c.Endpoint = "https://matrix.org/report-usage-stats/push" c.Endpoint = "https://matrix.org/report-usage-stats/push"
} }
func (c *ReportStats) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *ReportStats) Verify(configErrs *ConfigErrors) {
if c.Enabled { if c.Enabled {
checkNotEmpty(configErrs, "global.report_stats.endpoint", c.Endpoint) checkNotEmpty(configErrs, "global.report_stats.endpoint", c.Endpoint)
} }
@ -344,7 +343,7 @@ func (c *Sentry) Defaults() {
c.Enabled = false c.Enabled = false
} }
func (c *Sentry) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *Sentry) Verify(configErrs *ConfigErrors) {
} }
type DatabaseOptions struct { type DatabaseOptions struct {
@ -364,8 +363,7 @@ func (c *DatabaseOptions) Defaults(conns int) {
c.ConnMaxLifetimeSeconds = -1 c.ConnMaxLifetimeSeconds = -1
} }
func (c *DatabaseOptions) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *DatabaseOptions) Verify(configErrs *ConfigErrors) {}
}
// MaxIdleConns returns maximum idle connections to the DB // MaxIdleConns returns maximum idle connections to the DB
func (c DatabaseOptions) MaxIdleConns() int { func (c DatabaseOptions) MaxIdleConns() int {
@ -397,7 +395,7 @@ func (c *DNSCacheOptions) Defaults() {
c.CacheLifetime = time.Minute * 5 c.CacheLifetime = time.Minute * 5
} }
func (c *DNSCacheOptions) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *DNSCacheOptions) Verify(configErrs *ConfigErrors) {
checkPositive(configErrs, "cache_size", int64(c.CacheSize)) checkPositive(configErrs, "cache_size", int64(c.CacheSize))
checkPositive(configErrs, "cache_lifetime", int64(c.CacheLifetime)) checkPositive(configErrs, "cache_lifetime", int64(c.CacheLifetime))
} }

View file

@ -41,11 +41,4 @@ func (c *JetStream) Defaults(opts DefaultOpts) {
} }
} }
func (c *JetStream) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *JetStream) Verify(configErrs *ConfigErrors) {}
if isMonolith { // polylith required configs below
return
}
// If we are running in a polylith deployment then we need at least
// one NATS JetStream server to talk to.
checkNotZero(configErrs, "global.jetstream.addresses", int64(len(c.Addresses)))
}

View file

@ -3,31 +3,19 @@ package config
type KeyServer struct { type KeyServer struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
InternalAPI InternalAPIOptions `yaml:"internal_api,omitempty"`
Database DatabaseOptions `yaml:"database,omitempty"` Database DatabaseOptions `yaml:"database,omitempty"`
} }
func (c *KeyServer) Defaults(opts DefaultOpts) { func (c *KeyServer) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.InternalAPI.Listen = "http://localhost:7779"
c.InternalAPI.Connect = "http://localhost:7779"
c.Database.Defaults(10)
}
if opts.Generate { if opts.Generate {
if !opts.Monolithic { if !opts.SingleDatabase {
c.Database.ConnectionString = "file:keyserver.db" c.Database.ConnectionString = "file:keyserver.db"
} }
} }
} }
func (c *KeyServer) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *KeyServer) Verify(configErrs *ConfigErrors) {
if isMonolith { // polylith required configs below
return
}
if c.Matrix.DatabaseOptions.ConnectionString == "" { if c.Matrix.DatabaseOptions.ConnectionString == "" {
checkNotEmpty(configErrs, "key_server.database.connection_string", string(c.Database.ConnectionString)) checkNotEmpty(configErrs, "key_server.database.connection_string", string(c.Database.ConnectionString))
} }
checkURL(configErrs, "key_server.internal_api.listen", string(c.InternalAPI.Listen))
checkURL(configErrs, "key_server.internal_api.connect", string(c.InternalAPI.Connect))
} }

View file

@ -7,9 +7,6 @@ import (
type MediaAPI struct { type MediaAPI struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
InternalAPI InternalAPIOptions `yaml:"internal_api,omitempty"`
ExternalAPI ExternalAPIOptions `yaml:"external_api,omitempty"`
// The MediaAPI database stores information about files uploaded and downloaded // The MediaAPI database stores information about files uploaded and downloaded
// by local users. It is only accessed by the MediaAPI. // by local users. It is only accessed by the MediaAPI.
Database DatabaseOptions `yaml:"database,omitempty"` Database DatabaseOptions `yaml:"database,omitempty"`
@ -39,12 +36,6 @@ type MediaAPI struct {
var DefaultMaxFileSizeBytes = FileSizeBytes(10485760) var DefaultMaxFileSizeBytes = FileSizeBytes(10485760)
func (c *MediaAPI) Defaults(opts DefaultOpts) { func (c *MediaAPI) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.InternalAPI.Listen = "http://localhost:7774"
c.InternalAPI.Connect = "http://localhost:7774"
c.ExternalAPI.Listen = "http://[::]:8074"
c.Database.Defaults(5)
}
c.MaxFileSizeBytes = DefaultMaxFileSizeBytes c.MaxFileSizeBytes = DefaultMaxFileSizeBytes
c.MaxThumbnailGenerators = 10 c.MaxThumbnailGenerators = 10
if opts.Generate { if opts.Generate {
@ -65,14 +56,14 @@ func (c *MediaAPI) Defaults(opts DefaultOpts) {
ResizeMethod: "scale", ResizeMethod: "scale",
}, },
} }
if !opts.Monolithic { if !opts.SingleDatabase {
c.Database.ConnectionString = "file:mediaapi.db" c.Database.ConnectionString = "file:mediaapi.db"
} }
c.BasePath = "./media_store" c.BasePath = "./media_store"
} }
} }
func (c *MediaAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *MediaAPI) Verify(configErrs *ConfigErrors) {
checkNotEmpty(configErrs, "media_api.base_path", string(c.BasePath)) checkNotEmpty(configErrs, "media_api.base_path", string(c.BasePath))
checkPositive(configErrs, "media_api.max_file_size_bytes", int64(c.MaxFileSizeBytes)) checkPositive(configErrs, "media_api.max_file_size_bytes", int64(c.MaxFileSizeBytes))
checkPositive(configErrs, "media_api.max_thumbnail_generators", int64(c.MaxThumbnailGenerators)) checkPositive(configErrs, "media_api.max_thumbnail_generators", int64(c.MaxThumbnailGenerators))
@ -81,13 +72,8 @@ func (c *MediaAPI) Verify(configErrs *ConfigErrors, isMonolith bool) {
checkPositive(configErrs, fmt.Sprintf("media_api.thumbnail_sizes[%d].width", i), int64(size.Width)) checkPositive(configErrs, fmt.Sprintf("media_api.thumbnail_sizes[%d].width", i), int64(size.Width))
checkPositive(configErrs, fmt.Sprintf("media_api.thumbnail_sizes[%d].height", i), int64(size.Height)) checkPositive(configErrs, fmt.Sprintf("media_api.thumbnail_sizes[%d].height", i), int64(size.Height))
} }
if isMonolith { // polylith required configs below
return
}
if c.Matrix.DatabaseOptions.ConnectionString == "" { if c.Matrix.DatabaseOptions.ConnectionString == "" {
checkNotEmpty(configErrs, "media_api.database.connection_string", string(c.Database.ConnectionString)) checkNotEmpty(configErrs, "media_api.database.connection_string", string(c.Database.ConnectionString))
} }
checkURL(configErrs, "media_api.internal_api.listen", string(c.InternalAPI.Listen))
checkURL(configErrs, "media_api.internal_api.connect", string(c.InternalAPI.Connect))
checkURL(configErrs, "media_api.external_api.listen", string(c.ExternalAPI.Listen))
} }

View file

@ -14,11 +14,8 @@ type MSCs struct {
} }
func (c *MSCs) Defaults(opts DefaultOpts) { func (c *MSCs) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.Database.Defaults(5)
}
if opts.Generate { if opts.Generate {
if !opts.Monolithic { if !opts.SingleDatabase {
c.Database.ConnectionString = "file:mscs.db" c.Database.ConnectionString = "file:mscs.db"
} }
} }
@ -34,10 +31,7 @@ func (c *MSCs) Enabled(msc string) bool {
return false return false
} }
func (c *MSCs) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *MSCs) Verify(configErrs *ConfigErrors) {
if isMonolith { // polylith required configs below
return
}
if c.Matrix.DatabaseOptions.ConnectionString == "" { if c.Matrix.DatabaseOptions.ConnectionString == "" {
checkNotEmpty(configErrs, "mscs.database.connection_string", string(c.Database.ConnectionString)) checkNotEmpty(configErrs, "mscs.database.connection_string", string(c.Database.ConnectionString))
} }

View file

@ -17,36 +17,21 @@ package config
type RelayAPI struct { type RelayAPI struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
InternalAPI InternalAPIOptions `yaml:"internal_api,omitempty"`
ExternalAPI ExternalAPIOptions `yaml:"external_api,omitempty"`
// The database stores information used by the relay queue to // The database stores information used by the relay queue to
// forward transactions to remote servers. // forward transactions to remote servers.
Database DatabaseOptions `yaml:"database,omitempty"` Database DatabaseOptions `yaml:"database,omitempty"`
} }
func (c *RelayAPI) Defaults(opts DefaultOpts) { func (c *RelayAPI) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.InternalAPI.Listen = "http://localhost:7775"
c.InternalAPI.Connect = "http://localhost:7775"
c.ExternalAPI.Listen = "http://[::]:8075"
c.Database.Defaults(10)
}
if opts.Generate { if opts.Generate {
if !opts.Monolithic { if !opts.SingleDatabase {
c.Database.ConnectionString = "file:relayapi.db" c.Database.ConnectionString = "file:relayapi.db"
} }
} }
} }
func (c *RelayAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *RelayAPI) Verify(configErrs *ConfigErrors) {
if isMonolith { // polylith required configs below
return
}
if c.Matrix.DatabaseOptions.ConnectionString == "" { if c.Matrix.DatabaseOptions.ConnectionString == "" {
checkNotEmpty(configErrs, "relay_api.database.connection_string", string(c.Database.ConnectionString)) checkNotEmpty(configErrs, "relay_api.database.connection_string", string(c.Database.ConnectionString))
} }
checkURL(configErrs, "relay_api.external_api.listen", string(c.ExternalAPI.Listen))
checkURL(configErrs, "relay_api.internal_api.listen", string(c.InternalAPI.Listen))
checkURL(configErrs, "relay_api.internal_api.connect", string(c.InternalAPI.Connect))
} }

View file

@ -3,31 +3,19 @@ package config
type RoomServer struct { type RoomServer struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
InternalAPI InternalAPIOptions `yaml:"internal_api,omitempty"`
Database DatabaseOptions `yaml:"database,omitempty"` Database DatabaseOptions `yaml:"database,omitempty"`
} }
func (c *RoomServer) Defaults(opts DefaultOpts) { func (c *RoomServer) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.InternalAPI.Listen = "http://localhost:7770"
c.InternalAPI.Connect = "http://localhost:7770"
c.Database.Defaults(20)
}
if opts.Generate { if opts.Generate {
if !opts.Monolithic { if !opts.SingleDatabase {
c.Database.ConnectionString = "file:roomserver.db" c.Database.ConnectionString = "file:roomserver.db"
} }
} }
} }
func (c *RoomServer) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *RoomServer) Verify(configErrs *ConfigErrors) {
if isMonolith { // polylith required configs below
return
}
if c.Matrix.DatabaseOptions.ConnectionString == "" { if c.Matrix.DatabaseOptions.ConnectionString == "" {
checkNotEmpty(configErrs, "room_server.database.connection_string", string(c.Database.ConnectionString)) checkNotEmpty(configErrs, "room_server.database.connection_string", string(c.Database.ConnectionString))
} }
checkURL(configErrs, "room_server.internal_api.listen", string(c.InternalAPI.Listen))
checkURL(configErrs, "room_server.internal_ap.connect", string(c.InternalAPI.Connect))
} }

View file

@ -3,9 +3,6 @@ package config
type SyncAPI struct { type SyncAPI struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
InternalAPI InternalAPIOptions `yaml:"internal_api,omitempty"`
ExternalAPI ExternalAPIOptions `yaml:"external_api,omitempty"`
Database DatabaseOptions `yaml:"database,omitempty"` Database DatabaseOptions `yaml:"database,omitempty"`
RealIPHeader string `yaml:"real_ip_header"` RealIPHeader string `yaml:"real_ip_header"`
@ -14,31 +11,19 @@ type SyncAPI struct {
} }
func (c *SyncAPI) Defaults(opts DefaultOpts) { func (c *SyncAPI) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.InternalAPI.Listen = "http://localhost:7773"
c.InternalAPI.Connect = "http://localhost:7773"
c.ExternalAPI.Listen = "http://localhost:8073"
c.Database.Defaults(20)
}
c.Fulltext.Defaults(opts) c.Fulltext.Defaults(opts)
if opts.Generate { if opts.Generate {
if !opts.Monolithic { if !opts.SingleDatabase {
c.Database.ConnectionString = "file:syncapi.db" c.Database.ConnectionString = "file:syncapi.db"
} }
} }
} }
func (c *SyncAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *SyncAPI) Verify(configErrs *ConfigErrors) {
c.Fulltext.Verify(configErrs, isMonolith) c.Fulltext.Verify(configErrs)
if isMonolith { // polylith required configs below
return
}
if c.Matrix.DatabaseOptions.ConnectionString == "" { if c.Matrix.DatabaseOptions.ConnectionString == "" {
checkNotEmpty(configErrs, "sync_api.database", string(c.Database.ConnectionString)) checkNotEmpty(configErrs, "sync_api.database", string(c.Database.ConnectionString))
} }
checkURL(configErrs, "sync_api.internal_api.listen", string(c.InternalAPI.Listen))
checkURL(configErrs, "sync_api.internal_api.connect", string(c.InternalAPI.Connect))
checkURL(configErrs, "sync_api.external_api.listen", string(c.ExternalAPI.Listen))
} }
type Fulltext struct { type Fulltext struct {
@ -54,7 +39,7 @@ func (f *Fulltext) Defaults(opts DefaultOpts) {
f.Language = "en" f.Language = "en"
} }
func (f *Fulltext) Verify(configErrs *ConfigErrors, isMonolith bool) { func (f *Fulltext) Verify(configErrs *ConfigErrors) {
if !f.Enabled { if !f.Enabled {
return return
} }

View file

@ -30,14 +30,13 @@ func TestLoadConfigRelative(t *testing.T) {
"/my/config/dir/matrix_key.pem": testKey, "/my/config/dir/matrix_key.pem": testKey,
"/my/config/dir/tls_cert.pem": testCert, "/my/config/dir/tls_cert.pem": testCert,
}.readFile, }.readFile,
false,
) )
if err != nil { if err != nil {
t.Error("failed to load config:", err) t.Error("failed to load config:", err)
} }
configErrors := &ConfigErrors{} configErrors := &ConfigErrors{}
cfg.Verify(configErrors, false) cfg.Verify(configErrors)
if len(*configErrors) > 0 { if len(*configErrors) > 0 {
for _, err := range *configErrors { for _, err := range *configErrors {
logrus.Errorf("Configuration error: %s", err) logrus.Errorf("Configuration error: %s", err)
@ -81,9 +80,6 @@ global:
jetstream: jetstream:
addresses: ["test"] addresses: ["test"]
app_service_api: app_service_api:
internal_api:
listen: http://localhost:7777
connect: http://localhost:7777
database: database:
connection_string: file:appservice.db connection_string: file:appservice.db
max_open_conns: 100 max_open_conns: 100
@ -91,11 +87,6 @@ app_service_api:
conn_max_lifetime: -1 conn_max_lifetime: -1
config_files: [] config_files: []
client_api: client_api:
internal_api:
listen: http://localhost:7771
connect: http://localhost:7771
external_api:
listen: http://[::]:8071
registration_disabled: true registration_disabled: true
registration_shared_secret: "" registration_shared_secret: ""
enable_registration_captcha: false enable_registration_captcha: false
@ -109,38 +100,16 @@ client_api:
turn_shared_secret: "" turn_shared_secret: ""
turn_username: "" turn_username: ""
turn_password: "" turn_password: ""
current_state_server:
internal_api:
listen: http://localhost:7782
connect: http://localhost:7782
database:
connection_string: file:currentstate.db
max_open_conns: 100
max_idle_conns: 2
conn_max_lifetime: -1
federation_api: federation_api:
internal_api:
listen: http://localhost:7772
connect: http://localhost:7772
external_api:
listen: http://[::]:8072
database: database:
connection_string: file:federationapi.db connection_string: file:federationapi.db
key_server: key_server:
internal_api:
listen: http://localhost:7779
connect: http://localhost:7779
database: database:
connection_string: file:keyserver.db connection_string: file:keyserver.db
max_open_conns: 100 max_open_conns: 100
max_idle_conns: 2 max_idle_conns: 2
conn_max_lifetime: -1 conn_max_lifetime: -1
media_api: media_api:
internal_api:
listen: http://localhost:7774
connect: http://localhost:7774
external_api:
listen: http://[::]:8074
database: database:
connection_string: file:mediaapi.db connection_string: file:mediaapi.db
max_open_conns: 100 max_open_conns: 100
@ -161,18 +130,12 @@ media_api:
height: 480 height: 480
method: scale method: scale
room_server: room_server:
internal_api:
listen: http://localhost:7770
connect: http://localhost:7770
database: database:
connection_string: file:roomserver.db connection_string: file:roomserver.db
max_open_conns: 100 max_open_conns: 100
max_idle_conns: 2 max_idle_conns: 2
conn_max_lifetime: -1 conn_max_lifetime: -1
server_key_api: server_key_api:
internal_api:
listen: http://localhost:7780
connect: http://localhost:7780
database: database:
connection_string: file:serverkeyapi.db connection_string: file:serverkeyapi.db
max_open_conns: 100 max_open_conns: 100
@ -186,18 +149,12 @@ server_key_api:
- key_id: ed25519:a_RXGa - key_id: ed25519:a_RXGa
public_key: l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ public_key: l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ
sync_api: sync_api:
internal_api:
listen: http://localhost:7773
connect: http://localhost:7773
database: database:
connection_string: file:syncapi.db connection_string: file:syncapi.db
max_open_conns: 100 max_open_conns: 100
max_idle_conns: 2 max_idle_conns: 2
conn_max_lifetime: -1 conn_max_lifetime: -1
user_api: user_api:
internal_api:
listen: http://localhost:7781
connect: http://localhost:7781
account_database: account_database:
connection_string: file:userapi_accounts.db connection_string: file:userapi_accounts.db
max_open_conns: 100 max_open_conns: 100
@ -209,11 +166,6 @@ user_api:
max_idle_conns: 2 max_idle_conns: 2
conn_max_lifetime: -1 conn_max_lifetime: -1
relay_api: relay_api:
internal_api:
listen: http://localhost:7775
connect: http://localhost:7775
external_api:
listen: http://[::]:8075
database: database:
connection_string: file:relayapi.db connection_string: file:relayapi.db
mscs: mscs:

View file

@ -5,8 +5,6 @@ import "golang.org/x/crypto/bcrypt"
type UserAPI struct { type UserAPI struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
InternalAPI InternalAPIOptions `yaml:"internal_api,omitempty"`
// The cost when hashing passwords. // The cost when hashing passwords.
BCryptCost int `yaml:"bcrypt_cost"` BCryptCost int `yaml:"bcrypt_cost"`
@ -28,28 +26,18 @@ type UserAPI struct {
const DefaultOpenIDTokenLifetimeMS = 3600000 // 60 minutes const DefaultOpenIDTokenLifetimeMS = 3600000 // 60 minutes
func (c *UserAPI) Defaults(opts DefaultOpts) { func (c *UserAPI) Defaults(opts DefaultOpts) {
if !opts.Monolithic {
c.InternalAPI.Listen = "http://localhost:7781"
c.InternalAPI.Connect = "http://localhost:7781"
c.AccountDatabase.Defaults(10)
}
c.BCryptCost = bcrypt.DefaultCost c.BCryptCost = bcrypt.DefaultCost
c.OpenIDTokenLifetimeMS = DefaultOpenIDTokenLifetimeMS c.OpenIDTokenLifetimeMS = DefaultOpenIDTokenLifetimeMS
if opts.Generate { if opts.Generate {
if !opts.Monolithic { if !opts.SingleDatabase {
c.AccountDatabase.ConnectionString = "file:userapi_accounts.db" c.AccountDatabase.ConnectionString = "file:userapi_accounts.db"
} }
} }
} }
func (c *UserAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *UserAPI) Verify(configErrs *ConfigErrors) {
checkPositive(configErrs, "user_api.openid_token_lifetime_ms", c.OpenIDTokenLifetimeMS) checkPositive(configErrs, "user_api.openid_token_lifetime_ms", c.OpenIDTokenLifetimeMS)
if isMonolith { // polylith required configs below
return
}
if c.Matrix.DatabaseOptions.ConnectionString == "" { if c.Matrix.DatabaseOptions.ConnectionString == "" {
checkNotEmpty(configErrs, "user_api.account_database.connection_string", string(c.AccountDatabase.ConnectionString)) checkNotEmpty(configErrs, "user_api.account_database.connection_string", string(c.AccountDatabase.ConnectionString))
} }
checkURL(configErrs, "user_api.internal_api.listen", string(c.InternalAPI.Listen))
checkURL(configErrs, "user_api.internal_api.connect", string(c.InternalAPI.Connect))
} }

View file

@ -43,7 +43,7 @@ func ParseFlags(monolith bool) *config.Dendrite {
logrus.Fatal("--config must be supplied") logrus.Fatal("--config must be supplied")
} }
cfg, err := config.Load(*configPath, monolith) cfg, err := config.Load(*configPath)
if err != nil { if err != nil {
logrus.Fatalf("Invalid config file: %s", err) logrus.Fatalf("Invalid config file: %s", err)

View file

@ -499,7 +499,7 @@ func assertUnsignedChildren(t *testing.T, ev gomatrixserverlib.ClientEvent, relT
} }
type testUserAPI struct { type testUserAPI struct {
userapi.UserInternalAPITrace userapi.UserInternalAPI
accessTokens map[string]userapi.Device accessTokens map[string]userapi.Device
} }
@ -516,7 +516,7 @@ func (u *testUserAPI) QueryAccessToken(ctx context.Context, req *userapi.QueryAc
type testRoomserverAPI struct { type testRoomserverAPI struct {
// use a trace API as it implements method stubs so we don't need to have them here. // use a trace API as it implements method stubs so we don't need to have them here.
// We'll override the functions we care about. // We'll override the functions we care about.
roomserver.RoomserverInternalAPITrace roomserver.RoomserverInternalAPI
userToJoinedRooms map[string][]string userToJoinedRooms map[string][]string
events map[string]*gomatrixserverlib.HeaderedEvent events map[string]*gomatrixserverlib.HeaderedEvent
} }
@ -548,8 +548,8 @@ func injectEvents(t *testing.T, userAPI userapi.UserInternalAPI, rsAPI roomserve
t.Helper() t.Helper()
cfg := &config.Dendrite{} cfg := &config.Dendrite{}
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: true,
}) })
cfg.Global.ServerName = "localhost" cfg.Global.ServerName = "localhost"
cfg.MSCs.Database.ConnectionString = "file:msc2836_test.db" cfg.MSCs.Database.ConnectionString = "file:msc2836_test.db"

View file

@ -33,8 +33,7 @@ func init() {
} }
// calculateHistoryVisibilityDuration stores the time it takes to // calculateHistoryVisibilityDuration stores the time it takes to
// calculate the history visibility. In polylith mode the roundtrip // calculate the history visibility.
// to the roomserver is included in this time.
var calculateHistoryVisibilityDuration = prometheus.NewHistogramVec( var calculateHistoryVisibilityDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{ prometheus.HistogramOpts{
Namespace: "dendrite", Namespace: "dendrite",

View file

@ -64,7 +64,7 @@ func (k *mockKeyAPI) QuerySignatures(ctx context.Context, req *keyapi.QuerySigna
} }
type mockRoomserverAPI struct { type mockRoomserverAPI struct {
api.RoomserverInternalAPITrace api.RoomserverInternalAPI
roomIDToJoinedMembers map[string][]string roomIDToJoinedMembers map[string][]string
} }

View file

@ -28,24 +28,24 @@ import (
func CreateBaseDendrite(t *testing.T, dbType test.DBType) (*base.BaseDendrite, func()) { func CreateBaseDendrite(t *testing.T, dbType test.DBType) (*base.BaseDendrite, func()) {
var cfg config.Dendrite var cfg config.Dendrite
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: false, Generate: false,
Monolithic: true, SingleDatabase: true,
}) })
cfg.Global.JetStream.InMemory = true cfg.Global.JetStream.InMemory = true
cfg.FederationAPI.KeyPerspectives = nil cfg.FederationAPI.KeyPerspectives = nil
switch dbType { switch dbType {
case test.DBTypePostgres: case test.DBTypePostgres:
cfg.Global.Defaults(config.DefaultOpts{ // autogen a signing key cfg.Global.Defaults(config.DefaultOpts{ // autogen a signing key
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: true,
}) })
cfg.MediaAPI.Defaults(config.DefaultOpts{ // autogen a media path cfg.MediaAPI.Defaults(config.DefaultOpts{ // autogen a media path
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: true,
}) })
cfg.SyncAPI.Fulltext.Defaults(config.DefaultOpts{ // use in memory fts cfg.SyncAPI.Fulltext.Defaults(config.DefaultOpts{ // use in memory fts
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: true,
}) })
cfg.Global.ServerName = "test" cfg.Global.ServerName = "test"
// use a distinct prefix else concurrent postgres/sqlite runs will clash since NATS will use // use a distinct prefix else concurrent postgres/sqlite runs will clash since NATS will use
@ -58,7 +58,7 @@ func CreateBaseDendrite(t *testing.T, dbType test.DBType) (*base.BaseDendrite, f
MaxIdleConnections: 2, MaxIdleConnections: 2,
ConnMaxLifetimeSeconds: 60, ConnMaxLifetimeSeconds: 60,
} }
base := base.NewBaseDendrite(&cfg, "Test", base.DisableMetrics) base := base.NewBaseDendrite(&cfg, base.DisableMetrics)
return base, func() { return base, func() {
base.ShutdownDendrite() base.ShutdownDendrite()
base.WaitForShutdown() base.WaitForShutdown()
@ -66,8 +66,8 @@ func CreateBaseDendrite(t *testing.T, dbType test.DBType) (*base.BaseDendrite, f
} }
case test.DBTypeSQLite: case test.DBTypeSQLite:
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: false,
}) })
cfg.Global.ServerName = "test" cfg.Global.ServerName = "test"
@ -86,7 +86,7 @@ func CreateBaseDendrite(t *testing.T, dbType test.DBType) (*base.BaseDendrite, f
cfg.UserAPI.AccountDatabase.ConnectionString = config.DataSource(filepath.Join("file://", tempDir, "userapi.db")) cfg.UserAPI.AccountDatabase.ConnectionString = config.DataSource(filepath.Join("file://", tempDir, "userapi.db"))
cfg.RelayAPI.Database.ConnectionString = config.DataSource(filepath.Join("file://", tempDir, "relayapi.db")) cfg.RelayAPI.Database.ConnectionString = config.DataSource(filepath.Join("file://", tempDir, "relayapi.db"))
base := base.NewBaseDendrite(&cfg, "Test", base.DisableMetrics) base := base.NewBaseDendrite(&cfg, base.DisableMetrics)
return base, func() { return base, func() {
base.ShutdownDendrite() base.ShutdownDendrite()
base.WaitForShutdown() base.WaitForShutdown()
@ -102,14 +102,14 @@ func Base(cfg *config.Dendrite) (*base.BaseDendrite, nats.JetStreamContext, *nat
if cfg == nil { if cfg == nil {
cfg = &config.Dendrite{} cfg = &config.Dendrite{}
cfg.Defaults(config.DefaultOpts{ cfg.Defaults(config.DefaultOpts{
Generate: true, Generate: true,
Monolithic: true, SingleDatabase: false,
}) })
} }
cfg.Global.JetStream.InMemory = true cfg.Global.JetStream.InMemory = true
cfg.SyncAPI.Fulltext.InMemory = true cfg.SyncAPI.Fulltext.InMemory = true
cfg.FederationAPI.KeyPerspectives = nil cfg.FederationAPI.KeyPerspectives = nil
base := base.NewBaseDendrite(cfg, "Tests", base.DisableMetrics) base := base.NewBaseDendrite(cfg, base.DisableMetrics)
js, jc := base.NATS.Prepare(base.ProcessContext, &cfg.Global.JetStream) js, jc := base.NATS.Prepare(base.ProcessContext, &cfg.Global.JetStream)
return base, js, jc return base, js, jc
} }

View file

@ -1,219 +0,0 @@
// Copyright 2021 The Matrix.org Foundation C.I.C.
//
// 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.
package api
import (
"context"
"encoding/json"
"fmt"
"github.com/matrix-org/util"
)
// UserInternalAPITrace wraps a RoomserverInternalAPI and logs the
// complete request/response/error
type UserInternalAPITrace struct {
Impl UserInternalAPI
}
func (t *UserInternalAPITrace) InputAccountData(ctx context.Context, req *InputAccountDataRequest, res *InputAccountDataResponse) error {
err := t.Impl.InputAccountData(ctx, req, res)
util.GetLogger(ctx).Infof("InputAccountData req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformAccountCreation(ctx context.Context, req *PerformAccountCreationRequest, res *PerformAccountCreationResponse) error {
err := t.Impl.PerformAccountCreation(ctx, req, res)
util.GetLogger(ctx).Infof("PerformAccountCreation req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformPasswordUpdate(ctx context.Context, req *PerformPasswordUpdateRequest, res *PerformPasswordUpdateResponse) error {
err := t.Impl.PerformPasswordUpdate(ctx, req, res)
util.GetLogger(ctx).Infof("PerformPasswordUpdate req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformDeviceCreation(ctx context.Context, req *PerformDeviceCreationRequest, res *PerformDeviceCreationResponse) error {
err := t.Impl.PerformDeviceCreation(ctx, req, res)
util.GetLogger(ctx).Infof("PerformDeviceCreation req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformDeviceDeletion(ctx context.Context, req *PerformDeviceDeletionRequest, res *PerformDeviceDeletionResponse) error {
err := t.Impl.PerformDeviceDeletion(ctx, req, res)
util.GetLogger(ctx).Infof("PerformDeviceDeletion req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformLastSeenUpdate(ctx context.Context, req *PerformLastSeenUpdateRequest, res *PerformLastSeenUpdateResponse) error {
err := t.Impl.PerformLastSeenUpdate(ctx, req, res)
util.GetLogger(ctx).Infof("PerformLastSeenUpdate req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformDeviceUpdate(ctx context.Context, req *PerformDeviceUpdateRequest, res *PerformDeviceUpdateResponse) error {
err := t.Impl.PerformDeviceUpdate(ctx, req, res)
util.GetLogger(ctx).Infof("PerformDeviceUpdate req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformAccountDeactivation(ctx context.Context, req *PerformAccountDeactivationRequest, res *PerformAccountDeactivationResponse) error {
err := t.Impl.PerformAccountDeactivation(ctx, req, res)
util.GetLogger(ctx).Infof("PerformAccountDeactivation req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformOpenIDTokenCreation(ctx context.Context, req *PerformOpenIDTokenCreationRequest, res *PerformOpenIDTokenCreationResponse) error {
err := t.Impl.PerformOpenIDTokenCreation(ctx, req, res)
util.GetLogger(ctx).Infof("PerformOpenIDTokenCreation req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformKeyBackup(ctx context.Context, req *PerformKeyBackupRequest, res *PerformKeyBackupResponse) error {
err := t.Impl.PerformKeyBackup(ctx, req, res)
util.GetLogger(ctx).Infof("PerformKeyBackup req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformPusherSet(ctx context.Context, req *PerformPusherSetRequest, res *struct{}) error {
err := t.Impl.PerformPusherSet(ctx, req, res)
util.GetLogger(ctx).Infof("PerformPusherSet req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformPusherDeletion(ctx context.Context, req *PerformPusherDeletionRequest, res *struct{}) error {
err := t.Impl.PerformPusherDeletion(ctx, req, res)
util.GetLogger(ctx).Infof("PerformPusherDeletion req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformPushRulesPut(ctx context.Context, req *PerformPushRulesPutRequest, res *struct{}) error {
err := t.Impl.PerformPushRulesPut(ctx, req, res)
util.GetLogger(ctx).Infof("PerformPushRulesPut req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryKeyBackup(ctx context.Context, req *QueryKeyBackupRequest, res *QueryKeyBackupResponse) error {
err := t.Impl.QueryKeyBackup(ctx, req, res)
util.GetLogger(ctx).Infof("QueryKeyBackup req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryProfile(ctx context.Context, req *QueryProfileRequest, res *QueryProfileResponse) error {
err := t.Impl.QueryProfile(ctx, req, res)
util.GetLogger(ctx).Infof("QueryProfile req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryAccessToken(ctx context.Context, req *QueryAccessTokenRequest, res *QueryAccessTokenResponse) error {
err := t.Impl.QueryAccessToken(ctx, req, res)
util.GetLogger(ctx).Infof("QueryAccessToken req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryDevices(ctx context.Context, req *QueryDevicesRequest, res *QueryDevicesResponse) error {
err := t.Impl.QueryDevices(ctx, req, res)
util.GetLogger(ctx).Infof("QueryDevices req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryAccountData(ctx context.Context, req *QueryAccountDataRequest, res *QueryAccountDataResponse) error {
err := t.Impl.QueryAccountData(ctx, req, res)
util.GetLogger(ctx).Infof("QueryAccountData req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryDeviceInfos(ctx context.Context, req *QueryDeviceInfosRequest, res *QueryDeviceInfosResponse) error {
err := t.Impl.QueryDeviceInfos(ctx, req, res)
util.GetLogger(ctx).Infof("QueryDeviceInfos req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QuerySearchProfiles(ctx context.Context, req *QuerySearchProfilesRequest, res *QuerySearchProfilesResponse) error {
err := t.Impl.QuerySearchProfiles(ctx, req, res)
util.GetLogger(ctx).Infof("QuerySearchProfiles req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryOpenIDToken(ctx context.Context, req *QueryOpenIDTokenRequest, res *QueryOpenIDTokenResponse) error {
err := t.Impl.QueryOpenIDToken(ctx, req, res)
util.GetLogger(ctx).Infof("QueryOpenIDToken req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryPushers(ctx context.Context, req *QueryPushersRequest, res *QueryPushersResponse) error {
err := t.Impl.QueryPushers(ctx, req, res)
util.GetLogger(ctx).Infof("QueryPushers req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryPushRules(ctx context.Context, req *QueryPushRulesRequest, res *QueryPushRulesResponse) error {
err := t.Impl.QueryPushRules(ctx, req, res)
util.GetLogger(ctx).Infof("QueryPushRules req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryNotifications(ctx context.Context, req *QueryNotificationsRequest, res *QueryNotificationsResponse) error {
err := t.Impl.QueryNotifications(ctx, req, res)
util.GetLogger(ctx).Infof("QueryNotifications req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) SetAvatarURL(ctx context.Context, req *PerformSetAvatarURLRequest, res *PerformSetAvatarURLResponse) error {
err := t.Impl.SetAvatarURL(ctx, req, res)
util.GetLogger(ctx).Infof("SetAvatarURL req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryNumericLocalpart(ctx context.Context, req *QueryNumericLocalpartRequest, res *QueryNumericLocalpartResponse) error {
err := t.Impl.QueryNumericLocalpart(ctx, req, res)
util.GetLogger(ctx).Infof("QueryNumericLocalpart req= res=%+v", js(res))
return err
}
func (t *UserInternalAPITrace) QueryAccountAvailability(ctx context.Context, req *QueryAccountAvailabilityRequest, res *QueryAccountAvailabilityResponse) error {
err := t.Impl.QueryAccountAvailability(ctx, req, res)
util.GetLogger(ctx).Infof("QueryAccountAvailability req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) SetDisplayName(ctx context.Context, req *PerformUpdateDisplayNameRequest, res *PerformUpdateDisplayNameResponse) error {
err := t.Impl.SetDisplayName(ctx, req, res)
util.GetLogger(ctx).Infof("SetDisplayName req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryAccountByPassword(ctx context.Context, req *QueryAccountByPasswordRequest, res *QueryAccountByPasswordResponse) error {
err := t.Impl.QueryAccountByPassword(ctx, req, res)
util.GetLogger(ctx).Infof("QueryAccountByPassword req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryLocalpartForThreePID(ctx context.Context, req *QueryLocalpartForThreePIDRequest, res *QueryLocalpartForThreePIDResponse) error {
err := t.Impl.QueryLocalpartForThreePID(ctx, req, res)
util.GetLogger(ctx).Infof("QueryLocalpartForThreePID req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryThreePIDsForLocalpart(ctx context.Context, req *QueryThreePIDsForLocalpartRequest, res *QueryThreePIDsForLocalpartResponse) error {
err := t.Impl.QueryThreePIDsForLocalpart(ctx, req, res)
util.GetLogger(ctx).Infof("QueryThreePIDsForLocalpart req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformForgetThreePID(ctx context.Context, req *PerformForgetThreePIDRequest, res *struct{}) error {
err := t.Impl.PerformForgetThreePID(ctx, req, res)
util.GetLogger(ctx).Infof("PerformForgetThreePID req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformSaveThreePIDAssociation(ctx context.Context, req *PerformSaveThreePIDAssociationRequest, res *struct{}) error {
err := t.Impl.PerformSaveThreePIDAssociation(ctx, req, res)
util.GetLogger(ctx).Infof("PerformSaveThreePIDAssociation req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryAccountByLocalpart(ctx context.Context, req *QueryAccountByLocalpartRequest, res *QueryAccountByLocalpartResponse) error {
err := t.Impl.QueryAccountByLocalpart(ctx, req, res)
util.GetLogger(ctx).Infof("QueryAccountByLocalpart req=%+v res=%+v", js(req), js(res))
return err
}
func js(thing interface{}) string {
b, err := json.Marshal(thing)
if err != nil {
return fmt.Sprintf("Marshal error:%s", err)
}
return string(b)
}

View file

@ -1,39 +0,0 @@
// Copyright 2021 The Matrix.org Foundation C.I.C.
//
// 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.
package api
import (
"context"
"github.com/matrix-org/util"
)
func (t *UserInternalAPITrace) PerformLoginTokenCreation(ctx context.Context, req *PerformLoginTokenCreationRequest, res *PerformLoginTokenCreationResponse) error {
err := t.Impl.PerformLoginTokenCreation(ctx, req, res)
util.GetLogger(ctx).Infof("PerformLoginTokenCreation req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) PerformLoginTokenDeletion(ctx context.Context, req *PerformLoginTokenDeletionRequest, res *PerformLoginTokenDeletionResponse) error {
err := t.Impl.PerformLoginTokenDeletion(ctx, req, res)
util.GetLogger(ctx).Infof("PerformLoginTokenDeletion req=%+v res=%+v", js(req), js(res))
return err
}
func (t *UserInternalAPITrace) QueryLoginToken(ctx context.Context, req *QueryLoginTokenRequest, res *QueryLoginTokenResponse) error {
err := t.Impl.QueryLoginToken(ctx, req, res)
util.GetLogger(ctx).Infof("QueryLoginToken req=%+v res=%+v", js(req), js(res))
return err
}

View file

@ -1,454 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// 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.
package inthttp
import (
"context"
"errors"
"net/http"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/userapi/api"
)
// HTTP paths for the internal HTTP APIs
const (
InputAccountDataPath = "/userapi/inputAccountData"
PerformDeviceCreationPath = "/userapi/performDeviceCreation"
PerformAccountCreationPath = "/userapi/performAccountCreation"
PerformPasswordUpdatePath = "/userapi/performPasswordUpdate"
PerformDeviceDeletionPath = "/userapi/performDeviceDeletion"
PerformLastSeenUpdatePath = "/userapi/performLastSeenUpdate"
PerformDeviceUpdatePath = "/userapi/performDeviceUpdate"
PerformAccountDeactivationPath = "/userapi/performAccountDeactivation"
PerformOpenIDTokenCreationPath = "/userapi/performOpenIDTokenCreation"
PerformKeyBackupPath = "/userapi/performKeyBackup"
PerformPusherSetPath = "/pushserver/performPusherSet"
PerformPusherDeletionPath = "/pushserver/performPusherDeletion"
PerformPushRulesPutPath = "/pushserver/performPushRulesPut"
PerformSetAvatarURLPath = "/userapi/performSetAvatarURL"
PerformSetDisplayNamePath = "/userapi/performSetDisplayName"
PerformForgetThreePIDPath = "/userapi/performForgetThreePID"
PerformSaveThreePIDAssociationPath = "/userapi/performSaveThreePIDAssociation"
QueryKeyBackupPath = "/userapi/queryKeyBackup"
QueryProfilePath = "/userapi/queryProfile"
QueryAccessTokenPath = "/userapi/queryAccessToken"
QueryDevicesPath = "/userapi/queryDevices"
QueryAccountDataPath = "/userapi/queryAccountData"
QueryDeviceInfosPath = "/userapi/queryDeviceInfos"
QuerySearchProfilesPath = "/userapi/querySearchProfiles"
QueryOpenIDTokenPath = "/userapi/queryOpenIDToken"
QueryPushersPath = "/pushserver/queryPushers"
QueryPushRulesPath = "/pushserver/queryPushRules"
QueryNotificationsPath = "/pushserver/queryNotifications"
QueryNumericLocalpartPath = "/userapi/queryNumericLocalpart"
QueryAccountAvailabilityPath = "/userapi/queryAccountAvailability"
QueryAccountByPasswordPath = "/userapi/queryAccountByPassword"
QueryLocalpartForThreePIDPath = "/userapi/queryLocalpartForThreePID"
QueryThreePIDsForLocalpartPath = "/userapi/queryThreePIDsForLocalpart"
QueryAccountByLocalpartPath = "/userapi/queryAccountType"
)
// NewUserAPIClient creates a UserInternalAPI implemented by talking to a HTTP POST API.
// If httpClient is nil an error is returned
func NewUserAPIClient(
apiURL string,
httpClient *http.Client,
) (api.UserInternalAPI, error) {
if httpClient == nil {
return nil, errors.New("NewUserAPIClient: httpClient is <nil>")
}
return &httpUserInternalAPI{
apiURL: apiURL,
httpClient: httpClient,
}, nil
}
type httpUserInternalAPI struct {
apiURL string
httpClient *http.Client
}
func (h *httpUserInternalAPI) InputAccountData(ctx context.Context, req *api.InputAccountDataRequest, res *api.InputAccountDataResponse) error {
return httputil.CallInternalRPCAPI(
"InputAccountData", h.apiURL+InputAccountDataPath,
h.httpClient, ctx, req, res,
)
}
func (h *httpUserInternalAPI) PerformAccountCreation(
ctx context.Context,
request *api.PerformAccountCreationRequest,
response *api.PerformAccountCreationResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAccountCreation", h.apiURL+PerformAccountCreationPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformPasswordUpdate(
ctx context.Context,
request *api.PerformPasswordUpdateRequest,
response *api.PerformPasswordUpdateResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformPasswordUpdate", h.apiURL+PerformPasswordUpdatePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformDeviceCreation(
ctx context.Context,
request *api.PerformDeviceCreationRequest,
response *api.PerformDeviceCreationResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformDeviceCreation", h.apiURL+PerformDeviceCreationPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformDeviceDeletion(
ctx context.Context,
request *api.PerformDeviceDeletionRequest,
response *api.PerformDeviceDeletionResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformDeviceDeletion", h.apiURL+PerformDeviceDeletionPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformLastSeenUpdate(
ctx context.Context,
request *api.PerformLastSeenUpdateRequest,
response *api.PerformLastSeenUpdateResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformLastSeen", h.apiURL+PerformLastSeenUpdatePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformDeviceUpdate(
ctx context.Context,
request *api.PerformDeviceUpdateRequest,
response *api.PerformDeviceUpdateResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformDeviceUpdate", h.apiURL+PerformDeviceUpdatePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformAccountDeactivation(
ctx context.Context,
request *api.PerformAccountDeactivationRequest,
response *api.PerformAccountDeactivationResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAccountDeactivation", h.apiURL+PerformAccountDeactivationPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformOpenIDTokenCreation(
ctx context.Context,
request *api.PerformOpenIDTokenCreationRequest,
response *api.PerformOpenIDTokenCreationResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformOpenIDTokenCreation", h.apiURL+PerformOpenIDTokenCreationPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryProfile(
ctx context.Context,
request *api.QueryProfileRequest,
response *api.QueryProfileResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryProfile", h.apiURL+QueryProfilePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryDeviceInfos(
ctx context.Context,
request *api.QueryDeviceInfosRequest,
response *api.QueryDeviceInfosResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryDeviceInfos", h.apiURL+QueryDeviceInfosPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryAccessToken(
ctx context.Context,
request *api.QueryAccessTokenRequest,
response *api.QueryAccessTokenResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryAccessToken", h.apiURL+QueryAccessTokenPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryDevices(
ctx context.Context,
request *api.QueryDevicesRequest,
response *api.QueryDevicesResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryDevices", h.apiURL+QueryDevicesPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryAccountData(
ctx context.Context,
request *api.QueryAccountDataRequest,
response *api.QueryAccountDataResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryAccountData", h.apiURL+QueryAccountDataPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QuerySearchProfiles(
ctx context.Context,
request *api.QuerySearchProfilesRequest,
response *api.QuerySearchProfilesResponse,
) error {
return httputil.CallInternalRPCAPI(
"QuerySearchProfiles", h.apiURL+QuerySearchProfilesPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryOpenIDToken(
ctx context.Context,
request *api.QueryOpenIDTokenRequest,
response *api.QueryOpenIDTokenResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryOpenIDToken", h.apiURL+QueryOpenIDTokenPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformKeyBackup(
ctx context.Context,
request *api.PerformKeyBackupRequest,
response *api.PerformKeyBackupResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformKeyBackup", h.apiURL+PerformKeyBackupPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryKeyBackup(
ctx context.Context,
request *api.QueryKeyBackupRequest,
response *api.QueryKeyBackupResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryKeyBackup", h.apiURL+QueryKeyBackupPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryNotifications(
ctx context.Context,
request *api.QueryNotificationsRequest,
response *api.QueryNotificationsResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryNotifications", h.apiURL+QueryNotificationsPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformPusherSet(
ctx context.Context,
request *api.PerformPusherSetRequest,
response *struct{},
) error {
return httputil.CallInternalRPCAPI(
"PerformPusherSet", h.apiURL+PerformPusherSetPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformPusherDeletion(
ctx context.Context,
request *api.PerformPusherDeletionRequest,
response *struct{},
) error {
return httputil.CallInternalRPCAPI(
"PerformPusherDeletion", h.apiURL+PerformPusherDeletionPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryPushers(
ctx context.Context,
request *api.QueryPushersRequest,
response *api.QueryPushersResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryPushers", h.apiURL+QueryPushersPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformPushRulesPut(
ctx context.Context,
request *api.PerformPushRulesPutRequest,
response *struct{},
) error {
return httputil.CallInternalRPCAPI(
"PerformPushRulesPut", h.apiURL+PerformPushRulesPutPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryPushRules(
ctx context.Context,
request *api.QueryPushRulesRequest,
response *api.QueryPushRulesResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryPushRules", h.apiURL+QueryPushRulesPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) SetAvatarURL(
ctx context.Context,
request *api.PerformSetAvatarURLRequest,
response *api.PerformSetAvatarURLResponse,
) error {
return httputil.CallInternalRPCAPI(
"SetAvatarURL", h.apiURL+PerformSetAvatarURLPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryNumericLocalpart(
ctx context.Context,
request *api.QueryNumericLocalpartRequest,
response *api.QueryNumericLocalpartResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryNumericLocalpart", h.apiURL+QueryNumericLocalpartPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryAccountAvailability(
ctx context.Context,
request *api.QueryAccountAvailabilityRequest,
response *api.QueryAccountAvailabilityResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryAccountAvailability", h.apiURL+QueryAccountAvailabilityPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryAccountByPassword(
ctx context.Context,
request *api.QueryAccountByPasswordRequest,
response *api.QueryAccountByPasswordResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryAccountByPassword", h.apiURL+QueryAccountByPasswordPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) SetDisplayName(
ctx context.Context,
request *api.PerformUpdateDisplayNameRequest,
response *api.PerformUpdateDisplayNameResponse,
) error {
return httputil.CallInternalRPCAPI(
"SetDisplayName", h.apiURL+PerformSetDisplayNamePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryLocalpartForThreePID(
ctx context.Context,
request *api.QueryLocalpartForThreePIDRequest,
response *api.QueryLocalpartForThreePIDResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryLocalpartForThreePID", h.apiURL+QueryLocalpartForThreePIDPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryThreePIDsForLocalpart(
ctx context.Context,
request *api.QueryThreePIDsForLocalpartRequest,
response *api.QueryThreePIDsForLocalpartResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryThreePIDsForLocalpart", h.apiURL+QueryThreePIDsForLocalpartPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformForgetThreePID(
ctx context.Context,
request *api.PerformForgetThreePIDRequest,
response *struct{},
) error {
return httputil.CallInternalRPCAPI(
"PerformForgetThreePID", h.apiURL+PerformForgetThreePIDPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) PerformSaveThreePIDAssociation(
ctx context.Context,
request *api.PerformSaveThreePIDAssociationRequest,
response *struct{},
) error {
return httputil.CallInternalRPCAPI(
"PerformSaveThreePIDAssociation", h.apiURL+PerformSaveThreePIDAssociationPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpUserInternalAPI) QueryAccountByLocalpart(
ctx context.Context,
req *api.QueryAccountByLocalpartRequest,
res *api.QueryAccountByLocalpartResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryAccountByLocalpart", h.apiURL+QueryAccountByLocalpartPath,
h.httpClient, ctx, req, res,
)
}

Some files were not shown because too many files have changed in this diff Show more