Browse Source

🔙 Backport 2c15276 from v5/master to master

- Compared to 2c15276: changed socketsHttpHandler to HttpClientHandler due to legacy .NET Framework
- Use System.Net.Http.HttpClient for GeositeUpdater
- New update check mechanism: first download checksum and compare, only download GeoSite DB on different checksum
- Verifiy downloaded GeoSite DB by comparing sha256sum before committing the change
tags/4.2.0.0
database64128 4 years ago
parent
commit
728e01580c
No known key found for this signature in database GPG Key ID: 1CA27546BEDB8B01
5 changed files with 133 additions and 24 deletions
  1. +88
    -17
      shadowsocks-csharp/Controller/Service/GeositeUpdater.cs
  2. +0
    -5
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  3. +2
    -2
      shadowsocks-csharp/View/MenuViewController.cs
  4. +7
    -0
      shadowsocks-csharp/packages.config
  5. +36
    -0
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 88
- 17
shadowsocks-csharp/Controller/Service/GeositeUpdater.cs View File

@@ -9,6 +9,9 @@ using System.Text;
using Newtonsoft.Json;
using Shadowsocks.Model;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Security.Cryptography;

namespace Shadowsocks.Controller
{
@@ -32,23 +35,37 @@ namespace Shadowsocks.Controller

private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat");

private static HttpClientHandler httpClientHandler;
private static HttpClient httpClient;
private static readonly string GEOSITE_URL = "https://github.com/v2ray/domain-list-community/raw/release/dlc.dat";
private static readonly string GEOSITE_SHA256SUM_URL = "https://github.com/v2ray/domain-list-community/raw/release/dlc.dat.sha256sum";
private static byte[] geositeDB;

public static readonly Dictionary<string, IList<DomainObject>> Geosites = new Dictionary<string, IList<DomainObject>>();

static GeositeUpdater()
{
if (!File.Exists(DATABASE_PATH))
//socketsHttpHandler = new SocketsHttpHandler();
//httpClient = new HttpClient(socketsHttpHandler);
if (File.Exists(DATABASE_PATH) && new FileInfo(DATABASE_PATH).Length > 0)
{
geositeDB = File.ReadAllBytes(DATABASE_PATH);
}
else
{
geositeDB = Resources.dlc_dat;
File.WriteAllBytes(DATABASE_PATH, Resources.dlc_dat);
}
LoadGeositeList();
}

static void LoadGeositeList(byte[] data = null)
/// <summary>
/// load new GeoSite data from geositeDB
/// </summary>
static void LoadGeositeList()
{
data = data ?? File.ReadAllBytes(DATABASE_PATH);
var list = GeositeList.Parser.ParseFrom(data);
var list = GeositeList.Parser.ParseFrom(geositeDB);
foreach (var item in list.Entries)
{
Geosites[item.GroupName.ToLower()] = item.Domains;
@@ -61,9 +78,12 @@ namespace Shadowsocks.Controller
Error = null;
}

public static void UpdatePACFromGeosite(Configuration config)
public static async Task UpdatePACFromGeosite()
{
string geositeUrl = GEOSITE_URL;
string geositeSha256sumUrl = GEOSITE_SHA256SUM_URL;
SHA256 mySHA256 = SHA256.Create();
var config = Program.MainController.GetCurrentConfiguration();
string group = config.geositeGroup;
bool blacklist = config.geositeBlacklistMode;
@@ -73,31 +93,82 @@ namespace Shadowsocks.Controller
geositeUrl = config.geositeUrl;
}
logger.Info($"Checking Geosite from {geositeUrl}");
WebClient http = new WebClient();

// use System.Net.Http.HttpClient to download GeoSite db.
// NASTY workaround: new HttpClient every update
// because we can't change proxy on existing socketsHttpHandler instance
httpClientHandler = new HttpClientHandler();
httpClient = new HttpClient(httpClientHandler);
if (config.enabled)
{
http.Proxy = new WebProxy(
httpClientHandler.Proxy = new WebProxy(
config.isIPv6Enabled
? $"[{IPAddress.IPv6Loopback}]"
: IPAddress.Loopback.ToString(),
config.localPort);
}
http.DownloadDataCompleted += (o, e) =>

try
{
try
// download checksum first
var geositeSha256sum = await httpClient.GetStringAsync(geositeSha256sumUrl);
geositeSha256sum = geositeSha256sum.Substring(0, 64).ToUpper();
logger.Info($"Got Sha256sum: {geositeSha256sum}");
// compare downloaded checksum with local geositeDB
byte[] localDBHashBytes = mySHA256.ComputeHash(geositeDB);
string localDBHash = BitConverter.ToString(localDBHashBytes).Replace("-", String.Empty);
logger.Info($"Local Sha256sum: {localDBHash}");
// if already latest
if (geositeSha256sum == localDBHash)
{
logger.Info("Local GeoSite DB is already the latest.");
return;
}

// not latest. download new DB
var downloadedBytes = await httpClient.GetByteArrayAsync(geositeUrl);

// verify sha256sum
byte[] downloadedDBHashBytes = mySHA256.ComputeHash(downloadedBytes);
string downloadedDBHash = BitConverter.ToString(downloadedDBHashBytes).Replace("-", String.Empty);
logger.Info($"Actual Sha256sum: {downloadedDBHash}");
if (geositeSha256sum != downloadedDBHash)
{
File.WriteAllBytes(DATABASE_PATH, e.Result);
LoadGeositeList();
logger.Info("Sha256sum mismatch. Updating aborted.");
throw new Exception("Sha256sum mismatch");
}
else
{
logger.Info("Sha256sum verification successful.");
}

bool pacFileChanged = MergeAndWritePACFile(group, blacklist);
UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(pacFileChanged));
// write to geosite file
using (FileStream geositeFileStream = File.Create(DATABASE_PATH))
await geositeFileStream.WriteAsync(downloadedBytes, 0, downloadedBytes.Length);

// update stuff
geositeDB = downloadedBytes;
LoadGeositeList();
bool pacFileChanged = MergeAndWritePACFile(group, blacklist);
UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(pacFileChanged));
}
catch (Exception ex)
{
Error?.Invoke(null, new ErrorEventArgs(ex));
}
finally
{
if (httpClientHandler != null)
{
httpClientHandler.Dispose();
httpClientHandler = null;
}
catch (Exception ex)
if (httpClient != null)
{
Error?.Invoke(null, new ErrorEventArgs(ex));
httpClient.Dispose();
httpClient = null;
}
};
http.DownloadDataAsync(new Uri(geositeUrl));
}
}

public static bool MergeAndWritePACFile(string group, bool blacklist)


+ 0
- 5
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -415,11 +415,6 @@ namespace Shadowsocks.Controller
return $"ss://{url}{tag}";
}
public void UpdatePACFromGeosite()
{
GeositeUpdater.UpdatePACFromGeosite(_config);
}
public void UpdateStatisticsConfiguration(bool enabled)
{
if (availabilityStatistics != null)


+ 2
- 2
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -685,9 +685,9 @@ namespace Shadowsocks.View
controller.TouchPACFile();
}
private void UpdatePACFromGeositeItem_Click(object sender, EventArgs e)
private async void UpdatePACFromGeositeItem_Click(object sender, EventArgs e)
{
controller.UpdatePACFromGeosite();
await GeositeUpdater.UpdatePACFromGeosite();
}
private void EditUserRuleFileForGeositeItem_Click(object sender, EventArgs e)


+ 7
- 0
shadowsocks-csharp/packages.config View File

@@ -9,8 +9,15 @@
<package id="NLog" version="4.6.8" targetFramework="net472" />
<package id="StringEx.CS" version="0.3.1" targetFramework="net472" developmentDependency="true" />
<package id="System.Buffers" version="4.4.0" targetFramework="net472" />
<package id="System.IO" version="4.3.0" targetFramework="net472" />
<package id="System.Memory" version="4.5.2" targetFramework="net472" />
<package id="System.Net.Http" version="4.3.4" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" />
<package id="System.Runtime" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net472" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net472" />
<package id="ZXing.Net" version="0.16.5" targetFramework="net472" />
</packages>

+ 36
- 0
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -93,24 +93,60 @@
<Reference Include="System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.IO.Compression" />
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.ServiceModel" />
<Reference Include="System.Transactions" />
<Reference Include="System.Web" />


Loading…
Cancel
Save