FastGithubConfig.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using Microsoft.Extensions.Logging;
  2. using Microsoft.Extensions.Options;
  3. using System;
  4. using System.Collections.Concurrent;
  5. using System.Collections.Generic;
  6. using System.Diagnostics.CodeAnalysis;
  7. using System.Linq;
  8. using System.Net;
  9. namespace FastGithub.Configuration
  10. {
  11. /// <summary>
  12. /// FastGithub配置
  13. /// </summary>
  14. public class FastGithubConfig
  15. {
  16. private readonly ILogger<FastGithubConfig> logger;
  17. private SortedDictionary<DomainPattern, DomainConfig> domainConfigs;
  18. private ConcurrentDictionary<string, DomainConfig?> domainConfigCache;
  19. /// <summary>
  20. /// 未污染的dns
  21. /// </summary>
  22. public IPEndPoint PureDns { get; private set; }
  23. /// <summary>
  24. /// 速度快的dns
  25. /// </summary>
  26. public IPEndPoint FastDns { get; private set; }
  27. /// <summary>
  28. /// FastGithub配置
  29. /// </summary>
  30. /// <param name="options"></param>
  31. /// <param name="logger"></param>
  32. public FastGithubConfig(
  33. IOptionsMonitor<FastGithubOptions> options,
  34. ILogger<FastGithubConfig> logger)
  35. {
  36. this.logger = logger;
  37. var opt = options.CurrentValue;
  38. this.PureDns = opt.PureDns.ToIPEndPoint();
  39. this.FastDns = opt.FastDns.ToIPEndPoint();
  40. this.domainConfigs = ConvertDomainConfigs(opt.DomainConfigs);
  41. this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();
  42. options.OnChange(opt => this.Update(opt));
  43. }
  44. /// <summary>
  45. /// 更新配置
  46. /// </summary>
  47. /// <param name="options"></param>
  48. private void Update(FastGithubOptions options)
  49. {
  50. try
  51. {
  52. this.PureDns = options.PureDns.ToIPEndPoint();
  53. this.FastDns = options.FastDns.ToIPEndPoint();
  54. this.domainConfigs = ConvertDomainConfigs(options.DomainConfigs);
  55. this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();
  56. }
  57. catch (Exception ex)
  58. {
  59. this.logger.LogError(ex.Message);
  60. }
  61. }
  62. /// <summary>
  63. /// 配置转换
  64. /// </summary>
  65. /// <param name="domainConfigs"></param>
  66. /// <returns></returns>
  67. private static SortedDictionary<DomainPattern, DomainConfig> ConvertDomainConfigs(Dictionary<string, DomainConfig> domainConfigs)
  68. {
  69. var result = new SortedDictionary<DomainPattern, DomainConfig>();
  70. foreach (var kv in domainConfigs)
  71. {
  72. result.Add(new DomainPattern(kv.Key), kv.Value);
  73. }
  74. return result;
  75. }
  76. /// <summary>
  77. /// 是否匹配指定的域名
  78. /// </summary>
  79. /// <param name="domain"></param>
  80. /// <returns></returns>
  81. public bool IsMatch(string domain)
  82. {
  83. return this.domainConfigs.Keys.Any(item => item.IsMatch(domain));
  84. }
  85. /// <summary>
  86. /// 尝试获取域名配置
  87. /// </summary>
  88. /// <param name="domain"></param>
  89. /// <param name="value"></param>
  90. /// <returns></returns>
  91. public bool TryGetDomainConfig(string domain, [MaybeNullWhen(false)] out DomainConfig value)
  92. {
  93. value = this.domainConfigCache.GetOrAdd(domain, GetDomainConfig);
  94. return value != null;
  95. DomainConfig? GetDomainConfig(string domain)
  96. {
  97. var key = this.domainConfigs.Keys.FirstOrDefault(item => item.IsMatch(domain));
  98. return key == null ? null : this.domainConfigs[key];
  99. }
  100. }
  101. }
  102. }