about summary refs log tree commit diff
path: root/LibMatrix/Services/HomeserverResolverService.cs
diff options
context:
space:
mode:
Diffstat (limited to 'LibMatrix/Services/HomeserverResolverService.cs')
-rw-r--r--LibMatrix/Services/HomeserverResolverService.cs31
1 files changed, 20 insertions, 11 deletions
diff --git a/LibMatrix/Services/HomeserverResolverService.cs b/LibMatrix/Services/HomeserverResolverService.cs
index 06771b0..c8b6bb7 100644
--- a/LibMatrix/Services/HomeserverResolverService.cs
+++ b/LibMatrix/Services/HomeserverResolverService.cs
@@ -1,3 +1,4 @@
+using System.Collections.Concurrent;
 using System.Text.Json;
 using ArcaneLibs.Extensions;
 using LibMatrix.Extensions;
@@ -8,13 +9,11 @@ namespace LibMatrix.Services;
 public class HomeserverResolverService(ILogger<HomeserverResolverService>? logger = null) {
     private readonly MatrixHttpClient _httpClient = new();
 
-    private static readonly Dictionary<string, (string, string)> _wellKnownCache = new();
-    private static readonly Dictionary<string, SemaphoreSlim> _wellKnownSemaphores = new();
+    private static readonly ConcurrentDictionary<string, WellKnownUris> _wellKnownCache = new();
+    private static readonly ConcurrentDictionary<string, SemaphoreSlim> _wellKnownSemaphores = new();
 
-    public async Task<(string client, string server)> ResolveHomeserverFromWellKnown(string homeserver) {
+    public async Task<WellKnownUris> ResolveHomeserverFromWellKnown(string homeserver) {
         if (homeserver is null) throw new ArgumentNullException(nameof(homeserver));
-        // if(!_wellKnownSemaphores.ContainsKey(homeserver))
-            // _wellKnownSemaphores[homeserver] = new(1, 1);
         _wellKnownSemaphores.TryAdd(homeserver, new(1, 1));
         await _wellKnownSemaphores[homeserver].WaitAsync();
         if (_wellKnownCache.TryGetValue(homeserver, out var known)) {
@@ -23,11 +22,11 @@ public class HomeserverResolverService(ILogger<HomeserverResolverService>? logge
         }
         
         logger?.LogInformation("Resolving homeserver: {}", homeserver);
-        var res = (
-            await _tryResolveFromClientWellknown(homeserver),
-            await _tryResolveFromServerWellknown(homeserver)
-        );
-        _wellKnownCache.Add(homeserver, res!);
+        var res = new WellKnownUris {
+            Client = await _tryResolveFromClientWellknown(homeserver),
+            Server = await _tryResolveFromServerWellknown(homeserver)
+        };
+        _wellKnownCache.TryAdd(homeserver, res);
         _wellKnownSemaphores[homeserver].Release();
         return res;
     }
@@ -54,6 +53,11 @@ public class HomeserverResolverService(ILogger<HomeserverResolverService>? logge
             return hs;
         }
 
+        // fallback: most servers host these on the same location
+        var clientUrl = await _tryResolveFromClientWellknown(homeserver);
+        if (clientUrl is not null && await _httpClient.CheckSuccessStatus($"{clientUrl}/_matrix/federation/v1/version"))
+            return clientUrl;
+
         logger?.LogInformation("No server well-known...");
         return null;
     }
@@ -62,7 +66,12 @@ public class HomeserverResolverService(ILogger<HomeserverResolverService>? logge
         if (homeserver is null) throw new ArgumentNullException(nameof(homeserver));
         if (mxc is null) throw new ArgumentNullException(nameof(mxc));
         if (!mxc.StartsWith("mxc://")) throw new InvalidDataException("mxc must start with mxc://");
-        homeserver = (await ResolveHomeserverFromWellKnown(homeserver)).client;
+        homeserver = (await ResolveHomeserverFromWellKnown(homeserver)).Client;
         return mxc.Replace("mxc://", $"{homeserver}/_matrix/media/v3/download/");
     }
+
+    public class WellKnownUris {
+        public string? Client { get; set; }
+        public string? Server { get; set; }
+    }
 }