Browse Source

feature: get ISP

tags/3.0
icylogic 9 years ago
parent
commit
c08463710e
4 changed files with 121 additions and 26 deletions
  1. +65
    -22
      shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs
  2. +17
    -4
      shadowsocks-csharp/app.config
  3. +6
    -0
      shadowsocks-csharp/packages.config
  4. +33
    -0
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 65
- 22
shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs View File

@@ -2,12 +2,20 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using SimpleJson;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Shadowsocks.Model;
using SimpleJson = SimpleJson.SimpleJson;
using Timer = System.Threading.Timer;

namespace Shadowsocks.Controller
{
using DataUnit = KeyValuePair<string, string>;
using DataList = List<KeyValuePair<string, string>>;
class AvailabilityStatistics
{
private const string StatisticsFilesName = "shadowsocks.availability.csv";
@@ -51,35 +59,67 @@ namespace Shadowsocks.Controller
}
}

private void Evaluate(object obj)
//hardcode
//TODO: backup reliable isp&geolocation provider or a local database is required
private static async Task<DataList> getGeolocationAndISP()
{
Logging.Debug("Retrive information of geolocation and isp");
const string api = "http://ip-api.com/json";
var jsonString = await new HttpClient().GetStringAsync(api);
var ret = new DataList
{
new DataUnit(State.Geolocation, State.Unknown),
new DataUnit(State.ISP, State.Unknown),
};
dynamic obj;
if (!global::SimpleJson.SimpleJson.TryDeserializeObject(jsonString, out obj)) return ret;
string country = obj["country"];
string city = obj["city"];
string isp = obj["isp"];
string regionName= obj["regionName"];
if (country == null || city == null || isp == null || regionName == null) return ret;
ret[0] = new DataUnit(State.Geolocation, $"{country} {regionName} {city}");
ret[1] = new DataUnit(State.ISP, isp);
return ret;
}

private static async Task<List<DataList>> ICMPTest(Server server)
{
Logging.Debug("eveluating " + server.FriendlyName());
var ping = new Ping();
var state = (State) obj;
foreach (var server in _servers)
var ret = new List<DataList>();
foreach (var timestamp in Enumerable.Range(0, Repeat).Select(_ => DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")))
{
//ICMP echo. we can also set options and special bytes
var reply = await ping.SendTaskAsync(server.server, Timeout);
ret.Add(new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Timestamp", timestamp),
new KeyValuePair<string, string>("Server", server.FriendlyName()),
new KeyValuePair<string, string>("Status", reply?.Status.ToString()),
new KeyValuePair<string, string>("RoundtripTime", reply?.RoundtripTime.ToString())
//new KeyValuePair<string, string>("data", reply.Buffer.ToString()); // The data of reply
});
}
return ret;
}

private async void Evaluate(object obj)
{
var geolocationAndIsp = getGeolocationAndISP();
foreach (var dataLists in await TaskEx.WhenAll(_servers.Select(ICMPTest)))
{
Logging.Debug("eveluating " + server.FriendlyName());
foreach (var _ in Enumerable.Range(0, Repeat))
await geolocationAndIsp;
foreach (var dataList in dataLists)
{
//TODO: do simple analyze of data to provide friendly message, like package loss.
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
//ICMP echo. we can also set options and special bytes
//seems no need to use SendPingAsync:
var reply = ping.Send(server.server, Timeout);
state.Data = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Timestamp", timestamp),
new KeyValuePair<string, string>("Server", server.FriendlyName()),
new KeyValuePair<string, string>("Status", reply?.Status.ToString()),
new KeyValuePair<string, string>("RoundtripTime", reply?.RoundtripTime.ToString())
};
//state.data.Add(new KeyValuePair<string, string>("data", reply.Buffer.ToString())); // The data of reply
Append(state.Data);
Append(dataList, geolocationAndIsp.Result);
}
}
}

private static void Append(List<KeyValuePair<string, string>> data)
private static void Append(DataList dataList, IEnumerable<DataUnit> extra)
{
var data = dataList.Concat(extra);
var dataLine = string.Join(Delimiter, data.Select(kv => kv.Value).ToArray());
string[] lines;
if (!File.Exists(AvailabilityStatisticsFile))
@@ -102,7 +142,10 @@ namespace Shadowsocks.Controller

private class State
{
public List<KeyValuePair<string, string>> Data = new List<KeyValuePair<string, string>>();
public DataList dataList = new DataList();
public const string Geolocation = "Geolocation";
public const string ISP = "ISP";
public const string Unknown = "Unknown";
}
}
}

+ 17
- 4
shadowsocks-csharp/app.config View File

@@ -1,6 +1,19 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0"/>
<supportedRuntime version="v2.0.50727"/>
</startup></configuration>
<supportedRuntime version="v4.0" />
<supportedRuntime version="v2.0.50727" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

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

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.8" targetFramework="net4-client" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net4-client" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net4-client" />
</packages>

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

@@ -62,12 +62,39 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>3rd\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>3rd\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>3rd\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO, Version=2.6.8.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>3rd\Microsoft.Bcl.1.1.8\lib\net40\System.IO.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="System.Runtime, Version=2.6.8.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>3rd\Microsoft.Bcl.1.1.8\lib\net40\System.Runtime.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Threading.Tasks, Version=2.6.8.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>3rd\Microsoft.Bcl.1.1.8\lib\net40\System.Threading.Tasks.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Windows.Forms.DataVisualization" />
<Reference Include="System.Xaml" />
@@ -225,6 +252,7 @@
<None Include="Data\proxy.pac.txt.gz" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Resources\ss20.png" />
<None Include="Resources\ss16.png" />
<None Include="Resources\ss24.png" />
@@ -267,6 +295,11 @@
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="3rd\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('3rd\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('3rd\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('3rd\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">


Loading…
Cancel
Save