about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYour Name <you@example.com>2024-05-13 23:54:10 +0200
committerYour Name <you@example.com>2024-05-13 23:54:10 +0200
commit11c7786ea23d82d31cc54abe57d35fdd74cf1bd5 (patch)
treea5a244d1e97959ac98bd2b95cf2fa94edac0fe2d
parentFix some race conditions and some optimisation in HomeserverEmulator (diff)
downloadLibMatrix-11c7786ea23d82d31cc54abe57d35fdd74cf1bd5.tar.xz
Clearer error messages, fix bug in hs resolution
m---------ArcaneLibs0
-rw-r--r--LibMatrix/RoomTypes/GenericRoom.cs36
-rw-r--r--LibMatrix/Services/HomeserverProviderService.cs29
-rw-r--r--LibMatrix/Services/HomeserverResolverService.cs29
4 files changed, 55 insertions, 39 deletions
diff --git a/ArcaneLibs b/ArcaneLibs
-Subproject e885d07cb1c0e75a1a16fb473118a86ff3dc5d2
+Subproject 6f6b8e436eaa85eefa96dbf4d92b7aa21fb07ab
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs
index 742f5d9..f15327c 100644
--- a/LibMatrix/RoomTypes/GenericRoom.cs
+++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -228,43 +228,43 @@ public class GenericRoom {
     }
 
     public async IAsyncEnumerable<StateEventResponse> GetMembersEnumerableAsync(bool joinedOnly = true) {
-        var sw = Stopwatch.StartNew();
+        // var sw = Stopwatch.StartNew();
         var res = await Homeserver.ClientHttpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/members");
-        if (sw.ElapsedMilliseconds > 1000)
-            Console.WriteLine($"Members call responded in {sw.GetElapsedAndRestart()}");
-        else sw.Restart();
+        // if (sw.ElapsedMilliseconds > 1000)
+            // Console.WriteLine($"Members call responded in {sw.GetElapsedAndRestart()}");
+        // else sw.Restart();
         // var resText = await res.Content.ReadAsStringAsync();
         // Console.WriteLine($"Members call response read in {sw.GetElapsedAndRestart()}");
         var result = await JsonSerializer.DeserializeAsync<ChunkedStateEventResponse>(await res.Content.ReadAsStreamAsync(), new JsonSerializerOptions() {
             TypeInfoResolver = ChunkedStateEventResponseSerializerContext.Default
         });
-        if (sw.ElapsedMilliseconds > 100)
-            Console.WriteLine($"Members call deserialised in {sw.GetElapsedAndRestart()}");
-        else sw.Restart();
+        // if (sw.ElapsedMilliseconds > 100)
+            // Console.WriteLine($"Members call deserialised in {sw.GetElapsedAndRestart()}");
+        // else sw.Restart();
         foreach (var resp in result.Chunk) {
             if (resp?.Type != "m.room.member") continue;
             if (joinedOnly && resp.RawContent?["membership"]?.GetValue<string>() != "join") continue;
             yield return resp;
         }
 
-        if (sw.ElapsedMilliseconds > 100)
-            Console.WriteLine($"Members call iterated in {sw.GetElapsedAndRestart()}");
+        // if (sw.ElapsedMilliseconds > 100)
+            // Console.WriteLine($"Members call iterated in {sw.GetElapsedAndRestart()}");
     }
 
     public async Task<FrozenSet<StateEventResponse>> GetMembersListAsync(bool joinedOnly = true) {
-        var sw = Stopwatch.StartNew();
+        // var sw = Stopwatch.StartNew();
         var res = await Homeserver.ClientHttpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/members");
-        if (sw.ElapsedMilliseconds > 1000)
-            Console.WriteLine($"Members call responded in {sw.GetElapsedAndRestart()}");
-        else sw.Restart();
+        // if (sw.ElapsedMilliseconds > 1000)
+            // Console.WriteLine($"Members call responded in {sw.GetElapsedAndRestart()}");
+        // else sw.Restart();
         // var resText = await res.Content.ReadAsStringAsync();
         // Console.WriteLine($"Members call response read in {sw.GetElapsedAndRestart()}");
         var result = await JsonSerializer.DeserializeAsync<ChunkedStateEventResponse>(await res.Content.ReadAsStreamAsync(), new JsonSerializerOptions() {
             TypeInfoResolver = ChunkedStateEventResponseSerializerContext.Default
         });
-        if (sw.ElapsedMilliseconds > 100)
-            Console.WriteLine($"Members call deserialised in {sw.GetElapsedAndRestart()}");
-        else sw.Restart();
+        // if (sw.ElapsedMilliseconds > 100)
+            // Console.WriteLine($"Members call deserialised in {sw.GetElapsedAndRestart()}");
+        // else sw.Restart();
         var members = new List<StateEventResponse>();
         foreach (var resp in result.Chunk) {
             if (resp?.Type != "m.room.member") continue;
@@ -272,8 +272,8 @@ public class GenericRoom {
             members.Add(resp);
         }
 
-        if (sw.ElapsedMilliseconds > 100)
-            Console.WriteLine($"Members call iterated in {sw.GetElapsedAndRestart()}");
+        // if (sw.ElapsedMilliseconds > 100)
+            // Console.WriteLine($"Members call iterated in {sw.GetElapsedAndRestart()}");
         return members.ToFrozenSet();
     }
 
diff --git a/LibMatrix/Services/HomeserverProviderService.cs b/LibMatrix/Services/HomeserverProviderService.cs
index c61ef73..9867184 100644
--- a/LibMatrix/Services/HomeserverProviderService.cs
+++ b/LibMatrix/Services/HomeserverProviderService.cs
@@ -10,16 +10,19 @@ namespace LibMatrix.Services;
 public class HomeserverProviderService(ILogger<HomeserverProviderService> logger, HomeserverResolverService hsResolver) {
     private static SemaphoreCache<AuthenticatedHomeserverGeneric> AuthenticatedHomeserverCache = new();
     private static SemaphoreCache<RemoteHomeserver> RemoteHomeserverCache = new();
+    private static SemaphoreCache<FederationClient> FederationClientCache = new();
 
     public async Task<AuthenticatedHomeserverGeneric> GetAuthenticatedWithToken(string homeserver, string accessToken, string? proxy = null, string? impersonatedMxid = null,
-        bool useGeneric = false) {
+        bool useGeneric = false, bool enableClient = true, bool enableServer = true) {
+        if (!enableClient && !enableServer)
+            throw new ArgumentException("At least one of enableClient or enableServer must be true");
+
         return await AuthenticatedHomeserverCache.GetOrAdd($"{homeserver}{accessToken}{proxy}{impersonatedMxid}", async () => {
-            var wellKnownUris = await hsResolver.ResolveHomeserverFromWellKnown(homeserver);
+            var wellKnownUris = await hsResolver.ResolveHomeserverFromWellKnown(homeserver, enableClient, enableServer);
             var rhs = new RemoteHomeserver(homeserver, wellKnownUris, ref proxy);
-            
+
             AuthenticatedHomeserverGeneric? hs = null;
-            if (!useGeneric)
-            {
+            if (!useGeneric) {
                 ClientVersionsResponse? clientVersions = new();
                 try {
                     clientVersions = await rhs.GetClientVersionsAsync();
@@ -50,7 +53,7 @@ public class HomeserverProviderService(ILogger<HomeserverProviderService> logger
                     throw;
                 }
             }
-            
+
             hs ??= new AuthenticatedHomeserverGeneric(homeserver, wellKnownUris, ref proxy, accessToken);
 
             await hs.Initialise();
@@ -62,9 +65,17 @@ public class HomeserverProviderService(ILogger<HomeserverProviderService> logger
         });
     }
 
-    public async Task<RemoteHomeserver> GetRemoteHomeserver(string homeserver, string? proxy = null) =>
-        await RemoteHomeserverCache.GetOrAdd($"{homeserver}{proxy}",
-            async () => { return new RemoteHomeserver(homeserver, await hsResolver.ResolveHomeserverFromWellKnown(homeserver), ref proxy); });
+    public async Task<RemoteHomeserver> GetRemoteHomeserver(string homeserver, string? proxy = null, bool useCache = true, bool enableServer = true) =>
+        useCache
+            ? await RemoteHomeserverCache.GetOrAdd($"{homeserver}{proxy}",
+                async () => { return new RemoteHomeserver(homeserver, await hsResolver.ResolveHomeserverFromWellKnown(homeserver, enableServer: enableServer), ref proxy); })
+            : new RemoteHomeserver(homeserver, await hsResolver.ResolveHomeserverFromWellKnown(homeserver, enableServer: enableServer), ref proxy);
+
+    public async Task<FederationClient> GetFederationClient(string homeserver, string keyId, string? proxy = null, bool useCache = true) =>
+        useCache
+            ? await FederationClientCache.GetOrAdd($"{homeserver}{keyId}{proxy}",
+                async () => { return new FederationClient((await hsResolver.ResolveHomeserverFromWellKnown(homeserver, enableClient: false)).Server!, proxy); })
+            : new FederationClient((await hsResolver.ResolveHomeserverFromWellKnown(homeserver, enableClient: false)).Server!, proxy);
 
     public async Task<LoginResponse> Login(string homeserver, string user, string password, string? proxy = null) {
         var hs = await GetRemoteHomeserver(homeserver, proxy);
diff --git a/LibMatrix/Services/HomeserverResolverService.cs b/LibMatrix/Services/HomeserverResolverService.cs
index 42ad0a1..05ce733 100644
--- a/LibMatrix/Services/HomeserverResolverService.cs
+++ b/LibMatrix/Services/HomeserverResolverService.cs
@@ -14,7 +14,7 @@ namespace LibMatrix.Services;
 
 public class HomeserverResolverService {
     private readonly MatrixHttpClient _httpClient = new() {
-        Timeout = TimeSpan.FromMilliseconds(10000)
+        Timeout = TimeSpan.FromSeconds(60)
     };
 
     private static readonly SemaphoreCache<WellKnownUris> WellKnownCache = new();
@@ -30,40 +30,45 @@ public class HomeserverResolverService {
         }
     }
 
-    private static SemaphoreSlim _wellKnownSemaphore = new(1, 1);
+    // private static SemaphoreSlim _wellKnownSemaphore = new(1, 1);
 
-    public async Task<WellKnownUris> ResolveHomeserverFromWellKnown(string homeserver) {
+    public async Task<WellKnownUris> ResolveHomeserverFromWellKnown(string homeserver, bool enableClient = true, bool enableServer = true) {
         ArgumentNullException.ThrowIfNull(homeserver);
 
         return await WellKnownCache.GetOrAdd(homeserver, async () => {
-            await _wellKnownSemaphore.WaitAsync();
+            // await _wellKnownSemaphore.WaitAsync();
             _logger.LogTrace($"Resolving homeserver well-knowns: {homeserver}");
-            var client = _tryResolveClientEndpoint(homeserver);
+            var client = enableClient ? _tryResolveClientEndpoint(homeserver) : null;
+            var server = enableServer ? _tryResolveServerEndpoint(homeserver) : null;
 
             var res = new WellKnownUris();
 
             // try {
-            res.Client = await client ?? throw new Exception("Could not resolve client URL.");
+            if (client != null)
+                res.Client = await client ?? throw new Exception($"Could not resolve client URL for {homeserver}.");
             // }
             // catch (Exception e) {
             // _logger.LogError(e, "Error resolving client well-known for {hs}", homeserver);
             // }
 
-            var server = _tryResolveServerEndpoint(homeserver);
-
             // try {
-            res.Server = await server ?? throw new Exception("Could not resolve server URL.");
+            if (server != null)
+                res.Server = await server ?? throw new Exception($"Could not resolve server URL for {homeserver}.");
             // }
             // catch (Exception e) {
             // _logger.LogError(e, "Error resolving server well-known for {hs}", homeserver);
             // }
 
             _logger.LogInformation("Resolved well-knowns for {hs}: {json}", homeserver, res.ToJson(indent: false));
-            _wellKnownSemaphore.Release();
+            // _wellKnownSemaphore.Release();
             return res;
         });
     }
 
+    // private async Task<WellKnownUris> InternalResolveHomeserverFromWellKnown(string homeserver) {
+
+    // }
+
     private async Task<string?> _tryResolveClientEndpoint(string homeserver) {
         ArgumentNullException.ThrowIfNull(homeserver);
         _logger.LogTrace("Resolving client well-known: {homeserver}", homeserver);
@@ -90,7 +95,7 @@ public class HomeserverResolverService {
         if (!string.IsNullOrWhiteSpace(clientWellKnown?.Homeserver.BaseUrl))
             return clientWellKnown.Homeserver.BaseUrl;
 
-        _logger.LogInformation("No client well-known...");
+        _logger.LogInformation("No client well-known for {server}...", homeserver);
         return null;
     }
 
@@ -129,7 +134,7 @@ public class HomeserverResolverService {
         if (clientUrl is not null && await _httpClient.CheckSuccessStatus($"{clientUrl}/_matrix/federation/v1/version"))
             return clientUrl;
 
-        _logger.LogInformation("No server well-known...");
+        _logger.LogInformation("No server well-known for {server}...", homeserver);
         return null;
     }