diff --git a/cmd/dendrite/main.go b/cmd/dendrite/main.go new file mode 100644 index 000000000..0e5ab4033 --- /dev/null +++ b/cmd/dendrite/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "flag" + "fmt" + + "github.com/matrix-org/dendrite/cmd/dendrite/personalities" + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" +) + +type starter func(base *setup.BaseDendrite, cfg *config.Dendrite) + +// nolint:gocyclo +func main() { + cfg := setup.ParseFlags(true) + component := flag.Arg(0) + + base := setup.NewBaseDendrite(cfg, component, false) // TODO + defer base.Close() // nolint: errcheck + + components := map[string]starter{ + "appservice": personalities.Appservice, + "clientapi": personalities.ClientAPI, + "eduserver": personalities.EDUServer, + "federationapi": personalities.FederationAPI, + "federationsender": personalities.FederationSender, + "keyserver": personalities.KeyServer, + "mediaapi": personalities.MediaAPI, + "monolith": personalities.Monolith, + "roomserver": personalities.RoomServer, + "signingkeyserver": personalities.SigningKeyServer, + "syncapi": personalities.SyncAPI, + "userapi": personalities.UserAPI, + } + + if start, ok := components[component]; ok { + start(base, cfg) + } else { + fmt.Printf("dendrite: unknown component %q\n", component) + fmt.Println("valid components:") + for c := range components { + fmt.Printf("- %s\n", c) + } + } +} diff --git a/cmd/dendrite/personalities/appservice.go b/cmd/dendrite/personalities/appservice.go new file mode 100644 index 000000000..d8a641b5d --- /dev/null +++ b/cmd/dendrite/personalities/appservice.go @@ -0,0 +1,21 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/appservice" + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" +) + +func Appservice(base *setup.BaseDendrite, cfg *config.Dendrite) { + userAPI := base.UserAPIClient() + rsAPI := base.RoomserverHTTPClient() + + intAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) + appservice.AddInternalRoutes(base.InternalAPIMux, intAPI) + + base.SetupAndServeHTTP( + base.Cfg.AppServiceAPI.InternalAPI.Listen, // internal listener + setup.NoListener, // external listener + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/clientapi.go b/cmd/dendrite/personalities/clientapi.go new file mode 100644 index 000000000..9caecc64b --- /dev/null +++ b/cmd/dendrite/personalities/clientapi.go @@ -0,0 +1,31 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/clientapi" + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" + "github.com/matrix-org/dendrite/internal/transactions" +) + +func ClientAPI(base *setup.BaseDendrite, cfg *config.Dendrite) { + accountDB := base.CreateAccountsDB() + federation := base.CreateFederationClient() + + asQuery := base.AppserviceHTTPClient() + rsAPI := base.RoomserverHTTPClient() + fsAPI := base.FederationSenderHTTPClient() + eduInputAPI := base.EDUServerClient() + userAPI := base.UserAPIClient() + keyAPI := base.KeyServerHTTPClient() + + clientapi.AddPublicRoutes( + base.PublicClientAPIMux, &base.Cfg.ClientAPI, accountDB, federation, + rsAPI, eduInputAPI, asQuery, transactions.New(), fsAPI, userAPI, keyAPI, nil, + ) + + base.SetupAndServeHTTP( + base.Cfg.ClientAPI.InternalAPI.Listen, + base.Cfg.ClientAPI.ExternalAPI.Listen, + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/eduserver.go b/cmd/dendrite/personalities/eduserver.go new file mode 100644 index 000000000..ab0fbac4b --- /dev/null +++ b/cmd/dendrite/personalities/eduserver.go @@ -0,0 +1,19 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/eduserver" + "github.com/matrix-org/dendrite/eduserver/cache" + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" +) + +func EDUServer(base *setup.BaseDendrite, cfg *config.Dendrite) { + intAPI := eduserver.NewInternalAPI(base, cache.New(), base.UserAPIClient()) + eduserver.AddInternalRoutes(base.InternalAPIMux, intAPI) + + base.SetupAndServeHTTP( + base.Cfg.EDUServer.InternalAPI.Listen, // internal listener + setup.NoListener, // external listener + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/federationapi.go b/cmd/dendrite/personalities/federationapi.go new file mode 100644 index 000000000..69f498f19 --- /dev/null +++ b/cmd/dendrite/personalities/federationapi.go @@ -0,0 +1,29 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/federationapi" + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" +) + +func FederationAPI(base *setup.BaseDendrite, cfg *config.Dendrite) { + userAPI := base.UserAPIClient() + federation := base.CreateFederationClient() + serverKeyAPI := base.SigningKeyServerHTTPClient() + keyRing := serverKeyAPI.KeyRing() + fsAPI := base.FederationSenderHTTPClient() + rsAPI := base.RoomserverHTTPClient() + keyAPI := base.KeyServerHTTPClient() + + federationapi.AddPublicRoutes( + base.PublicFederationAPIMux, base.PublicKeyAPIMux, + &base.Cfg.FederationAPI, userAPI, federation, keyRing, + rsAPI, fsAPI, base.EDUServerClient(), keyAPI, + ) + + base.SetupAndServeHTTP( + base.Cfg.FederationAPI.InternalAPI.Listen, + base.Cfg.FederationAPI.ExternalAPI.Listen, + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/federationsender.go b/cmd/dendrite/personalities/federationsender.go new file mode 100644 index 000000000..965aca202 --- /dev/null +++ b/cmd/dendrite/personalities/federationsender.go @@ -0,0 +1,26 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/federationsender" + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" +) + +func FederationSender(base *setup.BaseDendrite, cfg *config.Dendrite) { + federation := base.CreateFederationClient() + + serverKeyAPI := base.SigningKeyServerHTTPClient() + keyRing := serverKeyAPI.KeyRing() + + rsAPI := base.RoomserverHTTPClient() + fsAPI := federationsender.NewInternalAPI( + base, federation, rsAPI, keyRing, + ) + federationsender.AddInternalRoutes(base.InternalAPIMux, fsAPI) + + base.SetupAndServeHTTP( + base.Cfg.FederationSender.InternalAPI.Listen, // internal listener + setup.NoListener, // external listener + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/keyserver.go b/cmd/dendrite/personalities/keyserver.go new file mode 100644 index 000000000..fbcd21bd8 --- /dev/null +++ b/cmd/dendrite/personalities/keyserver.go @@ -0,0 +1,20 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" + "github.com/matrix-org/dendrite/keyserver" +) + +func KeyServer(base *setup.BaseDendrite, cfg *config.Dendrite) { + intAPI := keyserver.NewInternalAPI(&base.Cfg.KeyServer, base.CreateFederationClient()) + intAPI.SetUserAPI(base.UserAPIClient()) + + keyserver.AddInternalRoutes(base.InternalAPIMux, intAPI) + + base.SetupAndServeHTTP( + base.Cfg.KeyServer.InternalAPI.Listen, // internal listener + setup.NoListener, // external listener + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/mediaapi.go b/cmd/dendrite/personalities/mediaapi.go new file mode 100644 index 000000000..da648bf28 --- /dev/null +++ b/cmd/dendrite/personalities/mediaapi.go @@ -0,0 +1,20 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" + "github.com/matrix-org/dendrite/mediaapi" +) + +func MediaAPI(base *setup.BaseDendrite, cfg *config.Dendrite) { + userAPI := base.UserAPIClient() + client := base.CreateClient() + + mediaapi.AddPublicRoutes(base.PublicMediaAPIMux, &base.Cfg.MediaAPI, userAPI, client) + + base.SetupAndServeHTTP( + base.Cfg.MediaAPI.InternalAPI.Listen, + base.Cfg.MediaAPI.ExternalAPI.Listen, + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/monolith.go b/cmd/dendrite/personalities/monolith.go new file mode 100644 index 000000000..b6da580de --- /dev/null +++ b/cmd/dendrite/personalities/monolith.go @@ -0,0 +1,144 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/appservice" + "github.com/matrix-org/dendrite/eduserver" + "github.com/matrix-org/dendrite/eduserver/cache" + "github.com/matrix-org/dendrite/federationsender" + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" + "github.com/matrix-org/dendrite/keyserver" + "github.com/matrix-org/dendrite/roomserver" + "github.com/matrix-org/dendrite/roomserver/api" + "github.com/matrix-org/dendrite/signingkeyserver" + "github.com/matrix-org/dendrite/userapi" + "github.com/sirupsen/logrus" +) + +func Monolith(base *setup.BaseDendrite, cfg *config.Dendrite) { + httpAddr := config.HTTPAddress("http://" + *httpBindAddr) + httpsAddr := config.HTTPAddress("https://" + *httpsBindAddr) + httpAPIAddr := httpAddr + + 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.EDUServer.InternalAPI.Connect = httpAPIAddr + cfg.FederationAPI.InternalAPI.Connect = httpAPIAddr + cfg.FederationSender.InternalAPI.Connect = httpAPIAddr + cfg.KeyServer.InternalAPI.Connect = httpAPIAddr + cfg.MediaAPI.InternalAPI.Connect = httpAPIAddr + cfg.RoomServer.InternalAPI.Connect = httpAPIAddr + cfg.SigningKeyServer.InternalAPI.Connect = httpAPIAddr + cfg.SyncAPI.InternalAPI.Connect = httpAPIAddr + } + + base := setup.NewBaseDendrite(cfg, "Monolith", *enableHTTPAPIs) + defer base.Close() // nolint: errcheck + + accountDB := base.CreateAccountsDB() + federation := base.CreateFederationClient() + + skAPI := signingkeyserver.NewInternalAPI( + &base.Cfg.SigningKeyServer, federation, base.Caches, + ) + if base.UseHTTPAPIs { + signingkeyserver.AddInternalRoutes(base.InternalAPIMux, skAPI, base.Caches) + skAPI = base.SigningKeyServerHTTPClient() + } + keyRing := skAPI.KeyRing() + + rsImpl := roomserver.NewInternalAPI( + base, keyRing, + ) + // call functions directly on the impl unless running in HTTP mode + rsAPI := rsImpl + if base.UseHTTPAPIs { + roomserver.AddInternalRoutes(base.InternalAPIMux, rsImpl) + rsAPI = base.RoomserverHTTPClient() + } + if traceInternal { + rsAPI = &api.RoomserverInternalAPITrace{ + Impl: rsAPI, + } + } + + fsAPI := federationsender.NewInternalAPI( + base, federation, rsAPI, keyRing, + ) + if base.UseHTTPAPIs { + federationsender.AddInternalRoutes(base.InternalAPIMux, fsAPI) + fsAPI = base.FederationSenderHTTPClient() + } + // 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 + rsImpl.SetFederationSenderAPI(fsAPI) + + keyAPI := keyserver.NewInternalAPI(&base.Cfg.KeyServer, fsAPI) + userAPI := userapi.NewInternalAPI(accountDB, &cfg.UserAPI, cfg.Derived.ApplicationServices, keyAPI) + keyAPI.SetUserAPI(userAPI) + + eduInputAPI := eduserver.NewInternalAPI( + base, cache.New(), userAPI, + ) + if base.UseHTTPAPIs { + eduserver.AddInternalRoutes(base.InternalAPIMux, eduInputAPI) + eduInputAPI = base.EDUServerClient() + } + + asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) + if base.UseHTTPAPIs { + appservice.AddInternalRoutes(base.InternalAPIMux, asAPI) + asAPI = base.AppserviceHTTPClient() + } + + monolith := setup.Monolith{ + Config: base.Cfg, + AccountDB: accountDB, + Client: base.CreateClient(), + FedClient: federation, + KeyRing: keyRing, + + AppserviceAPI: asAPI, + EDUInternalAPI: eduInputAPI, + FederationSenderAPI: fsAPI, + RoomserverAPI: rsAPI, + ServerKeyAPI: skAPI, + UserAPI: userAPI, + KeyAPI: keyAPI, + } + monolith.AddAllPublicRoutes( + base.PublicClientAPIMux, + base.PublicFederationAPIMux, + base.PublicKeyAPIMux, + base.PublicMediaAPIMux, + ) + + // 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( + setup.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 + select {} +} diff --git a/cmd/dendrite/personalities/roomserver.go b/cmd/dendrite/personalities/roomserver.go new file mode 100644 index 000000000..37de6fc70 --- /dev/null +++ b/cmd/dendrite/personalities/roomserver.go @@ -0,0 +1,23 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" + "github.com/matrix-org/dendrite/roomserver" +) + +func RoomServer(base *setup.BaseDendrite, cfg *config.Dendrite) { + serverKeyAPI := base.SigningKeyServerHTTPClient() + keyRing := serverKeyAPI.KeyRing() + + fsAPI := base.FederationSenderHTTPClient() + rsAPI := roomserver.NewInternalAPI(base, keyRing) + rsAPI.SetFederationSenderAPI(fsAPI) + roomserver.AddInternalRoutes(base.InternalAPIMux, rsAPI) + + base.SetupAndServeHTTP( + base.Cfg.RoomServer.InternalAPI.Listen, // internal listener + setup.NoListener, // external listener + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/signingkeyserver.go b/cmd/dendrite/personalities/signingkeyserver.go new file mode 100644 index 000000000..f94508022 --- /dev/null +++ b/cmd/dendrite/personalities/signingkeyserver.go @@ -0,0 +1,20 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" + "github.com/matrix-org/dendrite/signingkeyserver" +) + +func SigningKeyServer(base *setup.BaseDendrite, cfg *config.Dendrite) { + federation := base.CreateFederationClient() + + intAPI := signingkeyserver.NewInternalAPI(&base.Cfg.SigningKeyServer, federation, base.Caches) + signingkeyserver.AddInternalRoutes(base.InternalAPIMux, intAPI, base.Caches) + + base.SetupAndServeHTTP( + base.Cfg.SigningKeyServer.InternalAPI.Listen, + setup.NoListener, + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/syncapi.go b/cmd/dendrite/personalities/syncapi.go new file mode 100644 index 000000000..9355e1b93 --- /dev/null +++ b/cmd/dendrite/personalities/syncapi.go @@ -0,0 +1,26 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" + "github.com/matrix-org/dendrite/syncapi" +) + +func SyncAPI(base *setup.BaseDendrite, cfg *config.Dendrite) { + userAPI := base.UserAPIClient() + federation := base.CreateFederationClient() + + rsAPI := base.RoomserverHTTPClient() + + syncapi.AddPublicRoutes( + base.PublicClientAPIMux, userAPI, rsAPI, + base.KeyServerHTTPClient(), + federation, &cfg.SyncAPI, + ) + + base.SetupAndServeHTTP( + base.Cfg.SyncAPI.InternalAPI.Listen, + base.Cfg.SyncAPI.ExternalAPI.Listen, + nil, nil, + ) +} diff --git a/cmd/dendrite/personalities/userapi.go b/cmd/dendrite/personalities/userapi.go new file mode 100644 index 000000000..15cb681f4 --- /dev/null +++ b/cmd/dendrite/personalities/userapi.go @@ -0,0 +1,21 @@ +package personalities + +import ( + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/internal/setup" + "github.com/matrix-org/dendrite/userapi" +) + +func UserAPI(base *setup.BaseDendrite, cfg *config.Dendrite) { + accountDB := base.CreateAccountsDB() + + userAPI := userapi.NewInternalAPI(accountDB, &cfg.UserAPI, cfg.Derived.ApplicationServices, base.KeyServerHTTPClient()) + + userapi.AddInternalRoutes(base.InternalAPIMux, userAPI) + + base.SetupAndServeHTTP( + base.Cfg.UserAPI.InternalAPI.Listen, // internal listener + setup.NoListener, // external listener + nil, nil, + ) +}