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 changetags/4.2.0.0
@@ -9,6 +9,9 @@ using System.Text; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using Shadowsocks.Model; | using Shadowsocks.Model; | ||||
using System.Net; | using System.Net; | ||||
using System.Net.Http; | |||||
using System.Threading.Tasks; | |||||
using System.Security.Cryptography; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
@@ -32,23 +35,37 @@ namespace Shadowsocks.Controller | |||||
private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat"); | 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_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>>(); | public static readonly Dictionary<string, IList<DomainObject>> Geosites = new Dictionary<string, IList<DomainObject>>(); | ||||
static GeositeUpdater() | 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); | File.WriteAllBytes(DATABASE_PATH, Resources.dlc_dat); | ||||
} | } | ||||
LoadGeositeList(); | 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) | foreach (var item in list.Entries) | ||||
{ | { | ||||
Geosites[item.GroupName.ToLower()] = item.Domains; | Geosites[item.GroupName.ToLower()] = item.Domains; | ||||
@@ -61,9 +78,12 @@ namespace Shadowsocks.Controller | |||||
Error = null; | Error = null; | ||||
} | } | ||||
public static void UpdatePACFromGeosite(Configuration config) | |||||
public static async Task UpdatePACFromGeosite() | |||||
{ | { | ||||
string geositeUrl = GEOSITE_URL; | string geositeUrl = GEOSITE_URL; | ||||
string geositeSha256sumUrl = GEOSITE_SHA256SUM_URL; | |||||
SHA256 mySHA256 = SHA256.Create(); | |||||
var config = Program.MainController.GetCurrentConfiguration(); | |||||
string group = config.geositeGroup; | string group = config.geositeGroup; | ||||
bool blacklist = config.geositeBlacklistMode; | bool blacklist = config.geositeBlacklistMode; | ||||
@@ -73,31 +93,82 @@ namespace Shadowsocks.Controller | |||||
geositeUrl = config.geositeUrl; | geositeUrl = config.geositeUrl; | ||||
} | } | ||||
logger.Info($"Checking Geosite from {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) | if (config.enabled) | ||||
{ | { | ||||
http.Proxy = new WebProxy( | |||||
httpClientHandler.Proxy = new WebProxy( | |||||
config.isIPv6Enabled | config.isIPv6Enabled | ||||
? $"[{IPAddress.IPv6Loopback}]" | ? $"[{IPAddress.IPv6Loopback}]" | ||||
: IPAddress.Loopback.ToString(), | : IPAddress.Loopback.ToString(), | ||||
config.localPort); | 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) | public static bool MergeAndWritePACFile(string group, bool blacklist) | ||||
@@ -415,11 +415,6 @@ namespace Shadowsocks.Controller | |||||
return $"ss://{url}{tag}"; | return $"ss://{url}{tag}"; | ||||
} | } | ||||
public void UpdatePACFromGeosite() | |||||
{ | |||||
GeositeUpdater.UpdatePACFromGeosite(_config); | |||||
} | |||||
public void UpdateStatisticsConfiguration(bool enabled) | public void UpdateStatisticsConfiguration(bool enabled) | ||||
{ | { | ||||
if (availabilityStatistics != null) | if (availabilityStatistics != null) | ||||
@@ -685,9 +685,9 @@ namespace Shadowsocks.View | |||||
controller.TouchPACFile(); | 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) | private void EditUserRuleFileForGeositeItem_Click(object sender, EventArgs e) | ||||
@@ -9,8 +9,15 @@ | |||||
<package id="NLog" version="4.6.8" targetFramework="net472" /> | <package id="NLog" version="4.6.8" targetFramework="net472" /> | ||||
<package id="StringEx.CS" version="0.3.1" targetFramework="net472" developmentDependency="true" /> | <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.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.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.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.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" /> | <package id="ZXing.Net" version="0.16.5" targetFramework="net472" /> | ||||
</packages> | </packages> |
@@ -93,24 +93,60 @@ | |||||
<Reference Include="System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | <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> | <HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath> | ||||
</Reference> | </Reference> | ||||
<Reference Include="System.ComponentModel.Composition" /> | |||||
<Reference Include="System.Configuration" /> | <Reference Include="System.Configuration" /> | ||||
<Reference Include="System.Data" /> | <Reference Include="System.Data" /> | ||||
<Reference Include="System.Data.DataSetExtensions" /> | <Reference Include="System.Data.DataSetExtensions" /> | ||||
<Reference Include="System.Drawing" /> | <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.IO.Compression" /> | ||||
<Reference Include="System.Management" /> | <Reference Include="System.Management" /> | ||||
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | <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> | <HintPath>..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll</HintPath> | ||||
</Reference> | </Reference> | ||||
<Reference Include="System.Net" /> | <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" /> | ||||
<Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | <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> | <HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath> | ||||
</Reference> | </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"> | <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> | <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath> | ||||
</Reference> | </Reference> | ||||
<Reference Include="System.Runtime.Serialization" /> | <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.ServiceModel" /> | ||||
<Reference Include="System.Transactions" /> | <Reference Include="System.Transactions" /> | ||||
<Reference Include="System.Web" /> | <Reference Include="System.Web" /> | ||||