From cb92b267f46113f3c0a6138729ac584be6ae9399 Mon Sep 17 00:00:00 2001 From: "Emma [it/its]@Rory&" Date: Mon, 15 Jan 2024 02:11:36 +0100 Subject: Abstract FederationClient from RemoteHomeserver --- .../Homeservers/AuthenticatedHomeserverGeneric.cs | 12 +--- LibMatrix/Homeservers/FederationClient.cs | 67 ++++++++++++++++++++++ LibMatrix/Homeservers/RemoteHomeServer.cs | 41 +++++-------- LibMatrix/Services/HomeserverProviderService.cs | 2 +- 4 files changed, 85 insertions(+), 37 deletions(-) create mode 100644 LibMatrix/Homeservers/FederationClient.cs (limited to 'LibMatrix') diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs index 6fcd8e8..5db9a48 100644 --- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs +++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs @@ -19,6 +19,8 @@ public class AuthenticatedHomeserverGeneric(string serverName, string accessToke public static async Task Create(string serverName, string accessToken, string? proxy = null) where T : AuthenticatedHomeserverGeneric => await Create(typeof(T), serverName, accessToken, proxy) as T ?? throw new InvalidOperationException($"Failed to create instance of {typeof(T).Name}"); public static async Task Create(Type type, string serverName, string accessToken, string? proxy = null) { + if (string.IsNullOrWhiteSpace(proxy)) + proxy = null; if(!type.IsAssignableTo(typeof(AuthenticatedHomeserverGeneric))) throw new ArgumentException("Type must be a subclass of AuthenticatedHomeserverGeneric", nameof(type)); var instance = Activator.CreateInstance(type, serverName, accessToken) as AuthenticatedHomeserverGeneric ?? throw new InvalidOperationException($"Failed to create instance of {type.Name}"); @@ -29,23 +31,15 @@ public class AuthenticatedHomeserverGeneric(string serverName, string accessToke Authorization = new AuthenticationHeaderValue("Bearer", accessToken) } }; - instance.ServerHttpClient = new() { - Timeout = TimeSpan.FromMinutes(15), - DefaultRequestHeaders = { - Authorization = new AuthenticationHeaderValue("Bearer", accessToken) - } - }; + instance.FederationClient = await FederationClient.TryCreate(serverName, proxy); if (string.IsNullOrWhiteSpace(proxy)) { HomeserverResolverService.WellKnownUris? urls = await new HomeserverResolverService().ResolveHomeserverFromWellKnown(serverName); instance.ClientHttpClient.BaseAddress = new Uri(urls?.Client ?? throw new InvalidOperationException("Failed to resolve homeserver")); - instance.ServerHttpClient.BaseAddress = new Uri(urls?.Server ?? throw new InvalidOperationException("Failed to resolve homeserver")); } else { instance.ClientHttpClient.BaseAddress = new Uri(proxy); - instance.ServerHttpClient.BaseAddress = new Uri(proxy); instance.ClientHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", serverName); - instance.ServerHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", serverName); } instance.WhoAmI = await instance.ClientHttpClient.GetFromJsonAsync("/_matrix/client/v3/account/whoami"); diff --git a/LibMatrix/Homeservers/FederationClient.cs b/LibMatrix/Homeservers/FederationClient.cs new file mode 100644 index 0000000..6001862 --- /dev/null +++ b/LibMatrix/Homeservers/FederationClient.cs @@ -0,0 +1,67 @@ +using System.Net.Http.Json; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Web; +using ArcaneLibs.Extensions; +using LibMatrix.Extensions; +using LibMatrix.Responses; +using LibMatrix.Services; + +namespace LibMatrix.Homeservers; + +public class FederationClient(string baseUrl) { + public static async Task TryCreate(string baseUrl, string? proxy = null) { + try { + return await Create(baseUrl, proxy); + } + catch (Exception e) { + Console.WriteLine($"Failed to create homeserver {baseUrl}: {e.Message}"); + return null; + } + } + + public static async Task Create(string baseUrl, string? proxy = null) { + var homeserver = new FederationClient(baseUrl); + homeserver.WellKnownUris = await new HomeserverResolverService().ResolveHomeserverFromWellKnown(baseUrl); + if(string.IsNullOrWhiteSpace(proxy) && string.IsNullOrWhiteSpace(homeserver.WellKnownUris.Client)) + Console.WriteLine($"Failed to resolve homeserver client URI for {baseUrl}"); + if(string.IsNullOrWhiteSpace(proxy) && string.IsNullOrWhiteSpace(homeserver.WellKnownUris.Server)) + Console.WriteLine($"Failed to resolve homeserver server URI for {baseUrl}"); + + if (!string.IsNullOrWhiteSpace(homeserver.WellKnownUris.Server)) + homeserver.HttpClient = new() { + BaseAddress = new Uri(proxy ?? homeserver.WellKnownUris.Server ?? throw new InvalidOperationException($"Failed to resolve homeserver server URI for {baseUrl}")), + Timeout = TimeSpan.FromSeconds(120) + }; + + if (proxy is not null) { + homeserver.HttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", baseUrl); + } + + return homeserver; + } + + public string BaseUrl { get; } = baseUrl; + + public MatrixHttpClient HttpClient { get; set; } = null!; + public HomeserverResolverService.WellKnownUris WellKnownUris { get; set; } = null!; + + public async Task GetServerVersionAsync() { + return await HttpClient.GetFromJsonAsync("/_matrix/federation/v1/version"); + } + +} + +public class ServerVersionResponse { + [JsonPropertyName("server")] + public required ServerInfo Server { get; set; } + + // ReSharper disable once ClassNeverInstantiated.Global + public class ServerInfo { + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("version")] + public string Version { get; set; } + } +} \ No newline at end of file diff --git a/LibMatrix/Homeservers/RemoteHomeServer.cs b/LibMatrix/Homeservers/RemoteHomeServer.cs index 3423f54..f47dc4d 100644 --- a/LibMatrix/Homeservers/RemoteHomeServer.cs +++ b/LibMatrix/Homeservers/RemoteHomeServer.cs @@ -1,4 +1,5 @@ using System.Net.Http.Json; +using System.Runtime.CompilerServices; using System.Text.Json; using System.Text.Json.Serialization; using System.Web; @@ -21,22 +22,26 @@ public class RemoteHomeserver(string baseUrl) { } public static async Task Create(string baseUrl, string? proxy = null) { + if (string.IsNullOrWhiteSpace(proxy)) + proxy = null; var homeserver = new RemoteHomeserver(baseUrl); homeserver.WellKnownUris = await new HomeserverResolverService().ResolveHomeserverFromWellKnown(baseUrl); + if(string.IsNullOrWhiteSpace(homeserver.WellKnownUris.Client)) + Console.WriteLine($"Failed to resolve homeserver client URI for {baseUrl}"); + if(string.IsNullOrWhiteSpace(homeserver.WellKnownUris.Server)) + Console.WriteLine($"Failed to resolve homeserver server URI for {baseUrl}"); + + Console.WriteLine(homeserver.WellKnownUris.ToJson(ignoreNull:false)); + homeserver.ClientHttpClient = new() { - BaseAddress = new Uri(proxy ?? homeserver.WellKnownUris.Client ?? throw new InvalidOperationException("Failed to resolve homeserver")), + BaseAddress = new Uri(proxy ?? homeserver.WellKnownUris.Client ?? throw new InvalidOperationException($"Failed to resolve homeserver client URI for {baseUrl}")), Timeout = TimeSpan.FromSeconds(120) }; - if (!string.IsNullOrWhiteSpace(homeserver.WellKnownUris.Server)) - homeserver.ServerHttpClient = new() { - BaseAddress = new Uri(proxy ?? homeserver.WellKnownUris.Server ?? throw new InvalidOperationException("Failed to resolve homeserver")), - Timeout = TimeSpan.FromSeconds(120) - }; + + homeserver.FederationClient = await FederationClient.TryCreate(baseUrl, proxy); if (proxy is not null) { homeserver.ClientHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", baseUrl); - if (!string.IsNullOrWhiteSpace(homeserver.WellKnownUris.Server)) - homeserver.ServerHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", baseUrl); } return homeserver; @@ -46,7 +51,7 @@ public class RemoteHomeserver(string baseUrl) { public string BaseUrl { get; } = baseUrl; public MatrixHttpClient ClientHttpClient { get; set; } = null!; - public MatrixHttpClient ServerHttpClient { get; set; } = null!; + public FederationClient? FederationClient { get; set; } public HomeserverResolverService.WellKnownUris WellKnownUris { get; set; } = null!; public async Task GetProfileAsync(string mxid, bool useCache = false) { @@ -117,10 +122,6 @@ public class RemoteHomeserver(string baseUrl) { #endregion - public async Task GetServerVersionAsync() { - return await ServerHttpClient.GetFromJsonAsync("/_matrix/federation/v1/version"); - } - public string? ResolveMediaUri(string? mxcUri) { if (mxcUri is null) return null; if (mxcUri.StartsWith("https://")) return mxcUri; @@ -128,20 +129,6 @@ public class RemoteHomeserver(string baseUrl) { } } -public class ServerVersionResponse { - [JsonPropertyName("server")] - public required ServerInfo Server { get; set; } - - // ReSharper disable once ClassNeverInstantiated.Global - public class ServerInfo { - [JsonPropertyName("name")] - public string Name { get; set; } - - [JsonPropertyName("version")] - public string Version { get; set; } - } -} - public class AliasResult { [JsonPropertyName("room_id")] public string RoomId { get; set; } = null!; diff --git a/LibMatrix/Services/HomeserverProviderService.cs b/LibMatrix/Services/HomeserverProviderService.cs index 577a706..4cf74d1 100644 --- a/LibMatrix/Services/HomeserverProviderService.cs +++ b/LibMatrix/Services/HomeserverProviderService.cs @@ -42,7 +42,7 @@ public class HomeserverProviderService(ILogger logger if (clientVersions.UnstableFeatures.TryGetValue("gay.rory.mxapiextensions.v0", out bool a) && a) hs = await AuthenticatedHomeserverGeneric.Create(homeserver, accessToken, proxy); else { - var serverVersion = await rhs.GetServerVersionAsync(); + var serverVersion = await (rhs.FederationClient?.GetServerVersionAsync() ?? Task.FromResult(null)); if (serverVersion is { Server.Name: "Synapse" }) hs = await AuthenticatedHomeserverGeneric.Create(homeserver, accessToken, proxy); else -- cgit 1.4.1