├── WpfApp ├── Services │ ├── IRegionService.cs │ ├── DesignTimeRegionService.cs │ ├── RegionService.cs │ └── RegionFactory.cs ├── ViewModels │ ├── IMainWindowViewModel.cs │ ├── INodeListViewModel.cs │ ├── IRegionViewModel.cs │ ├── DesignTimeMainWindowViewModel.cs │ ├── MainWindowViewModel.cs │ ├── NodeListViewModel.cs │ ├── DesignTimeRegionViewModel.cs │ ├── DesignTimeNodeListViewModel.cs │ ├── LatencyViewModel.cs │ ├── NodeViewModel.cs │ └── RegionViewModel.cs ├── App.xaml ├── Views │ ├── NodeListUserControl.xaml.cs │ ├── RegionUserControl.xaml.cs │ ├── MainWindowView.xaml.cs │ ├── MainWindowView.xaml │ ├── RegionUserControl.xaml │ └── NodeListUserControl.xaml ├── AssemblyInfo.cs ├── WpfApp.csproj ├── App.xaml.cs └── app.manifest ├── Core ├── HostsManager │ ├── Host.cs │ ├── IHostsFileHandler.cs │ ├── HostsParser.cs │ ├── HostsFileHandler.cs │ └── HostsManager.cs ├── Core.csproj ├── Node │ └── Node.cs ├── Region │ └── Region.cs └── LatencyChecker │ ├── Latency.cs │ ├── LatencyService.cs │ └── UDPSession.cs ├── Node ├── Nanjing.txt ├── Beijing.txt ├── Chengdu.txt ├── 卡拉彼丘 Mudfish Custom Profiles │ ├── 卡拉彼丘 Mudfish Profile.json │ ├── 卡拉彼丘 北京 Beijing.json │ ├── 卡拉彼丘 南京 Nanjing.json │ ├── 卡拉彼丘 成都 Chengdu.json │ └── 卡拉彼丘 广州 Guangzhou.json ├── Guangzhou.txt ├── Seoul.txt ├── Hong Kong.txt ├── Tokyo.txt └── Singapore.txt ├── CoreTests ├── CoreTests.csproj ├── LatencyChecker │ ├── UDPSessionTests.cs │ ├── LatencyTests.cs │ └── LatencyServiceTests.cs └── HostsManager │ ├── HostsFileHandlerTests.cs │ └── HostsManagerTests.cs ├── LICENSE.txt ├── README.md ├── StrinovaNodeSwitcher.sln ├── .gitattributes └── .gitignore /WpfApp/Services/IRegionService.cs: -------------------------------------------------------------------------------- 1 | namespace WpfApp.Services 2 | { 3 | public interface IRegionService 4 | { 5 | Task LoadRegionsAsync(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /WpfApp/ViewModels/IMainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace WpfApp.ViewModels 2 | { 3 | public interface IMainWindowViewModel 4 | { 5 | IEnumerable Regions { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Core/HostsManager/Host.cs: -------------------------------------------------------------------------------- 1 | namespace Core.HostsManager 2 | { 3 | public class Host(string ip, string hostname) 4 | { 5 | public string IP { get; set; } = ip; 6 | public string Hostname { get; set; } = hostname; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Core/Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Core/Node/Node.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace Core.Node 4 | { 5 | public class Node(IPAddress address, int port) 6 | { 7 | public IPAddress? IPAddress { get; set; } = address; 8 | public int Port { get; set; } = port; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /WpfApp/App.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /WpfApp/ViewModels/INodeListViewModel.cs: -------------------------------------------------------------------------------- 1 | using Core.Node; 2 | using System.Collections.ObjectModel; 3 | 4 | namespace WpfApp.ViewModels 5 | { 6 | public interface INodeListViewModel 7 | { 8 | ObservableCollection NodeList { get; set; } 9 | int NodeCount { get; } 10 | void AddNode(Node node); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /WpfApp/ViewModels/IRegionViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace WpfApp.ViewModels 2 | { 3 | public interface IRegionViewModel 4 | { 5 | string Name { get; set; } 6 | INodeListViewModel Server { get; set; } 7 | NodeViewModel WorstServer { get; } 8 | //INodeListViewModel EdgeOne { get; set; } 9 | //NodeViewModel BestEdgeOne { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /WpfApp/Views/NodeListUserControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace WpfApp.Views 4 | { 5 | /// 6 | /// Interaction logic for NodeListUserControl.xaml 7 | /// 8 | public partial class NodeListUserControl : UserControl 9 | { 10 | public NodeListUserControl() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /WpfApp/Views/RegionUserControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace WpfApp.Views 4 | { 5 | public partial class RegionUserControl : UserControl 6 | { 7 | /// 8 | /// Interaction logic for RegionUserControl.xaml 9 | /// 10 | public RegionUserControl() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Core/Region/Region.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | 3 | namespace Core.Region 4 | { 5 | public class Region 6 | { 7 | public string Name { get; private set; } 8 | public ObservableCollection Nodes { get; private set; } 9 | 10 | public Region(string name) 11 | { 12 | Name = name; 13 | Nodes = []; 14 | } 15 | 16 | public void Add(Node.Node node) 17 | { 18 | Nodes.Add(node); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Node/Nanjing.txt: -------------------------------------------------------------------------------- 1 | Nanjing 2 | DNS 107 Standard query response 0x74c4 A klbqcp-prod-ping-nj-lb.gxpan.cn A 1.13.117.2 3 | 4 | 南京, Nanjing.nj:1번째 Server: 119.45.28.76 5 | 南京, Nanjing.nj:2번째 Server: 175.27.136.54 6 | 南京, Nanjing.nj:3번째 Server: 146.56.195.241 7 | 南京, Nanjing.nj:4번째 Server: 43.137.36.164 8 | 南京, Nanjing.nj:5번째 Server: 118.195.151.176 9 | 南京, Nanjing.nj:6번째 Server: 1.13.173.29 10 | 南京, Nanjing.nj:7번째 Server: 118.195.145.56 11 | 12 | 43.137.75.107/32 13 | 119.45.28.76/32 14 | 175.27.136.54/32 15 | 146.56.195.241/32 16 | 43.137.36.164/32 17 | 118.195.151.176/32 18 | 1.13.173.29/32 19 | 118.195.145.56/32 -------------------------------------------------------------------------------- /Node/Beijing.txt: -------------------------------------------------------------------------------- 1 | Beijing 2 | DNS 107 Standard query response 0x9042 A klbqcp-prod-ping-bj-lb.gxpan.cn A 43.137.75.107 3 | 4 | 北京, Beijing.bj:1번째 Server: 49.233.176.128 5 | 北京, Beijing.bj:2번째 Server: 43.143.191.156 6 | 北京, Beijing.bj:3번째 Server: 62.234.219.60 7 | 北京, Beijing.bj:4번째 Server: 101.42.168.183 8 | 北京, Beijing.bj:5번째 Server: 43.138.18.40 9 | 北京, Beijing.bj:6번째 Server: 82.156.40.10 10 | 北京, Beijing.bj:7번째 Server: 120.53.123.234 11 | 12 | 43.137.75.107/32 13 | 49.233.176.128/32 14 | 43.143.191.156/32 15 | 62.234.219.60/32 16 | 101.42.168.183/32 17 | 43.138.18.40/32 18 | 82.156.40.10/32 19 | 120.53.123.234/32 -------------------------------------------------------------------------------- /Node/Chengdu.txt: -------------------------------------------------------------------------------- 1 | Chengdu 2 | DNS 107 Standard query response 0xfa81 A klbqcp-prod-ping-cd-lb.gxpan.cn A 43.141.203.214 3 | 4 | 成都, Chengdu.cd:1번째 Server: 42.193.14.186 5 | 成都, Chengdu.cd:2번째 Server: 132.232.198.119 6 | 成都, Chengdu.cd:3번째 Server: 162.14.68.175 7 | 成都, Chengdu.cd:4번째 Server: 42.193.13.238 8 | 成都, Chengdu.cd:5번째 Server: 118.24.22.84 9 | 成都, Chengdu.cd:6번째 Server: 118.24.57.146 10 | 成都, Chengdu.cd:7번째 Server: 129.28.90.189 11 | 12 | 43.141.203.214/32 13 | 42.193.14.186/32 14 | 132.232.198.119/32 15 | 162.14.68.175/32 16 | 42.193.13.238/32 17 | 118.24.22.84/32 18 | 118.24.57.146/32 19 | 129.28.90.189/32 -------------------------------------------------------------------------------- /Node/卡拉彼丘 Mudfish Custom Profiles/卡拉彼丘 Mudfish Profile.json: -------------------------------------------------------------------------------- 1 | { 2 | "item": { 3 | "category": "game", 4 | "icon": "", 5 | "name": "\u5361\u62c9\u5f7c\u4e18", 6 | "rt": [ 7 | { 8 | "ip": "43.141.203.214", 9 | "netmask": "255.255.255.255" 10 | }, 11 | { 12 | "procname": "Calabiyau-Win64-Shipping.exe" 13 | } 14 | ], 15 | "rtt": [ 16 | { 17 | "family": "AF_INET", 18 | "ip": "43.141.203.214", 19 | "is_private": 0, 20 | "location": "\u6210\u90fd (Chengdu)", 21 | "protocol": "ICMP" 22 | } 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /Node/Guangzhou.txt: -------------------------------------------------------------------------------- 1 | Guangzhou 2 | DNS 107 Standard query response 0x35c4 A klbqcp-prod-ping-gz-lb.gxpan.cn A 119.91.241.217 3 | 4 | 广州, Guangzhou.gz:1번째 Server: 129.204.166.68 5 | 广州, Guangzhou.gz:2번째 Server: 114.132.155.237 6 | 广州, Guangzhou.gz:3번째 Server: 42.193.226.174 7 | 广州, Guangzhou.gz:4번째 Server: 43.138.139.109 8 | 广州, Guangzhou.gz:5번째 Server: 159.75.93.60 9 | 广州, Guangzhou.gz:6번째 Server: 81.71.156.229 10 | 广州, Guangzhou.gz:7번째 Server: 119.91.211.81 11 | 12 | 13 | 119.91.241.217/32 14 | 129.204.166.68/32 15 | 114.132.155.237/32 16 | 42.193.226.174/32 17 | 43.138.139.109/32 18 | 159.75.93.60/32 19 | 81.71.156.229/32 20 | 119.91.211.81/32 -------------------------------------------------------------------------------- /WpfApp/ViewModels/DesignTimeMainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using WpfApp.Services; 3 | 4 | namespace WpfApp.ViewModels 5 | { 6 | public class DesignTimeMainWindowViewModel : IMainWindowViewModel 7 | { 8 | private readonly ObservableCollection _regions; 9 | public IEnumerable Regions => _regions; 10 | public readonly IRegionService _regionService; 11 | 12 | public DesignTimeMainWindowViewModel() 13 | { 14 | _regions = []; 15 | _regionService = new DesignTimeRegionService(_regions); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WpfApp/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /WpfApp/ViewModels/MainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using System.Collections.ObjectModel; 3 | using WpfApp.Services; 4 | 5 | namespace WpfApp.ViewModels 6 | { 7 | public partial class MainWindowViewModel : ObservableObject, IMainWindowViewModel 8 | { 9 | private readonly ObservableCollection _regions; 10 | public IEnumerable Regions => _regions; 11 | private readonly IRegionService _regionService; 12 | 13 | public MainWindowViewModel() 14 | { 15 | _regions = []; 16 | _regionService = new RegionService(_regions); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /WpfApp/WpfApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WinExe 5 | net8.0-windows 6 | enable 7 | enable 8 | true 9 | app.manifest 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /WpfApp/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using WpfApp.ViewModels; 3 | using WpfApp.Views; 4 | 5 | namespace WpfApp 6 | { 7 | /// 8 | /// Interaction logic for App.xaml 9 | /// 10 | public partial class App : Application 11 | { 12 | protected override void OnStartup(StartupEventArgs e) 13 | { 14 | base.OnStartup(e); 15 | 16 | var mainWindow = new MainWindowView(); 17 | var mainWindowViewModel = new MainWindowViewModel(); 18 | 19 | mainWindow.DataContext = mainWindowViewModel; 20 | MainWindow = mainWindow; 21 | MainWindow.Show(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CoreTests/CoreTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | latest 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Core/HostsManager/IHostsFileHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Core.HostsManager 8 | { 9 | public interface IHostsFileHandler 10 | { 11 | /// 12 | /// Reads all lines from the hosts file. 13 | /// 14 | /// An array of strings representing the lines in the hosts file. 15 | string[] ReadHosts(); 16 | 17 | /// 18 | /// Writes the specified lines to the hosts file. 19 | /// 20 | /// The lines to write to the file. 21 | void WriteHosts(string[] lines); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WpfApp/ViewModels/NodeListViewModel.cs: -------------------------------------------------------------------------------- 1 | using Core.Node; 2 | using System.Collections.ObjectModel; 3 | 4 | namespace WpfApp.ViewModels 5 | { 6 | public class NodeListViewModel : INodeListViewModel 7 | { 8 | public ObservableCollection NodeList { get; set; } 9 | public int NodeCount => NodeList.Count; 10 | 11 | public NodeListViewModel() 12 | { 13 | NodeList = []; 14 | } 15 | 16 | public void AddNode(Node node) 17 | { 18 | // Invoke the UI thread to add the node 19 | App.Current.Dispatcher.Invoke(() => 20 | { 21 | NodeList.Add(new NodeViewModel(node, NodeCount + 1)); 22 | }); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WpfApp/Views/MainWindowView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Text; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Data; 6 | using System.Windows.Documents; 7 | using System.Windows.Input; 8 | using System.Windows.Media; 9 | using System.Windows.Media.Imaging; 10 | using System.Windows.Navigation; 11 | using System.Windows.Shapes; 12 | using WpfApp.ViewModels; 13 | using WpfApp.Views; 14 | 15 | namespace WpfApp.Views 16 | { 17 | public partial class MainWindowView : Window 18 | { 19 | /// 20 | /// Interaction logic for MainWindowView.xaml 21 | /// 22 | public MainWindowView() 23 | { 24 | InitializeComponent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Core/LatencyChecker/Latency.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | 3 | namespace Core.LatencyChecker 4 | { 5 | public class Latency 6 | { 7 | private const int MaxCapacity = 200; 8 | private readonly ConcurrentQueue _latencies; 9 | 10 | public Latency() 11 | { 12 | _latencies = []; 13 | } 14 | 15 | public void Add(float ping) 16 | { 17 | _latencies.Enqueue(ping); 18 | while (_latencies.Count > MaxCapacity) 19 | { 20 | // 맨 앞의 요소 제거 21 | _latencies.TryDequeue(out _); 22 | } 23 | } 24 | 25 | public void Clear() 26 | { 27 | while (_latencies.TryDequeue(out _)) { } 28 | } 29 | 30 | public ConcurrentQueue GetLatencyList() 31 | { 32 | return _latencies; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /WpfApp/ViewModels/DesignTimeRegionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace WpfApp.ViewModels 4 | { 5 | public class DesignTimeRegionViewModel : IRegionViewModel 6 | { 7 | public string Name { get; set; } 8 | public INodeListViewModel Server { get; set; } 9 | public NodeViewModel WorstServer => Server.NodeList.MaxBy(node => node.Latency.Score); 10 | public INodeListViewModel EdgeOne { get; set; } 11 | public NodeViewModel BestEdgeOne => EdgeOne.NodeList.MinBy(node => node.Latency.Score); 12 | 13 | public DesignTimeRegionViewModel() 14 | { 15 | Name = "Mock Region"; 16 | Server = new NodeListViewModel(); 17 | Server.AddNode(new(IPAddress.Parse("43.155.138.82"), 20000)); 18 | EdgeOne = new NodeListViewModel(); 19 | EdgeOne.AddNode(new(IPAddress.Parse("43.175.253.233"), 20000)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /WpfApp/ViewModels/DesignTimeNodeListViewModel.cs: -------------------------------------------------------------------------------- 1 | using Core.Node; 2 | using System.Collections.ObjectModel; 3 | using System.Net; 4 | 5 | namespace WpfApp.ViewModels 6 | { 7 | public class DesignTimeNodeListViewModel : INodeListViewModel 8 | { 9 | public ObservableCollection NodeList { get; set; } 10 | public int NodeCount => NodeList.Count; 11 | 12 | public DesignTimeNodeListViewModel() 13 | { 14 | NodeList = []; 15 | AddNode(new Node(IPAddress.Parse("43.155.138.82"), 20000)); 16 | AddNode(new Node(IPAddress.Parse("43.128.155.169"), 20000)); 17 | } 18 | 19 | public void AddNode(Node node) 20 | { 21 | // Invoke the UI thread to add the node 22 | App.Current.Dispatcher.Invoke(() => 23 | { 24 | NodeList.Add(new NodeViewModel(node, NodeCount + 1)); 25 | }); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /WpfApp/Services/DesignTimeRegionService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using WpfApp.ViewModels; 3 | 4 | namespace WpfApp.Services 5 | { 6 | public class DesignTimeRegionService : IRegionService 7 | { 8 | private readonly ObservableCollection _regions; 9 | private RegionFactory _regionFactory; 10 | 11 | public DesignTimeRegionService(ObservableCollection regions) 12 | { 13 | _regions = regions; 14 | _regionFactory = new(_regions); 15 | 16 | Task.Run(() => LoadRegionsAsync()); 17 | } 18 | 19 | public async Task LoadRegionsAsync() 20 | { 21 | var tasks = new[] 22 | { 23 | _regionFactory.LoadNodesAsync("南京, Nanjing", "nj"), 24 | _regionFactory.LoadNodesAsync("广州, Guangzhou", "gz"), 25 | }; 26 | 27 | await Task.WhenAll(tasks); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WpfApp/Services/RegionService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using WpfApp.ViewModels; 3 | 4 | namespace WpfApp.Services 5 | { 6 | public class RegionService : IRegionService 7 | { 8 | private readonly ObservableCollection _regions; 9 | private RegionFactory _regionFactory; 10 | 11 | public RegionService(ObservableCollection regions) 12 | { 13 | _regions = regions; 14 | _regionFactory = new(_regions); 15 | 16 | Task.Run(() => LoadRegionsAsync()); 17 | } 18 | 19 | public async Task LoadRegionsAsync() 20 | { 21 | var tasks = new[] 22 | { 23 | _regionFactory.LoadNodesAsync("成都, Chengdu", "cd"), 24 | _regionFactory.LoadNodesAsync("北京, Beijing", "bj"), 25 | _regionFactory.LoadNodesAsync("南京, Nanjing", "nj"), 26 | _regionFactory.LoadNodesAsync("广州, Guangzhou", "gz"), 27 | }; 28 | 29 | await Task.WhenAll(tasks); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Node/卡拉彼丘 Mudfish Custom Profiles/卡拉彼丘 北京 Beijing.json: -------------------------------------------------------------------------------- 1 | { 2 | "item": { 3 | "category": "game", 4 | "icon": "", 5 | "name": "\u5361\u62c9\u5f7c\u4e18 \u5317\u4eac Beijing", 6 | "rt": [ 7 | { 8 | "ip": "43.137.75.107", 9 | "netmask": "255.255.255.255" 10 | }, 11 | { 12 | "ip": "49.233.176.128", 13 | "netmask": "255.255.255.255" 14 | }, 15 | { 16 | "ip": "43.143.191.156", 17 | "netmask": "255.255.255.255" 18 | }, 19 | { 20 | "ip": "62.234.219.60", 21 | "netmask": "255.255.255.255" 22 | }, 23 | { 24 | "ip": "101.42.168.183", 25 | "netmask": "255.255.255.255" 26 | }, 27 | { 28 | "ip": "43.138.18.40", 29 | "netmask": "255.255.255.255" 30 | }, 31 | { 32 | "ip": "82.156.40.10", 33 | "netmask": "255.255.255.255" 34 | }, 35 | { 36 | "ip": "120.53.123.234", 37 | "netmask": "255.255.255.255" 38 | } 39 | ], 40 | "rtt": [ 41 | { 42 | "family": "AF_INET", 43 | "ip": "43.137.75.107", 44 | "is_private": 0, 45 | "location": "43.137.75.107", 46 | "protocol": "ICMP" 47 | } 48 | ] 49 | } 50 | } -------------------------------------------------------------------------------- /Node/卡拉彼丘 Mudfish Custom Profiles/卡拉彼丘 南京 Nanjing.json: -------------------------------------------------------------------------------- 1 | { 2 | "item": { 3 | "category": "game", 4 | "icon": "", 5 | "name": "\u5361\u62c9\u5f7c\u4e18 \u5357\u4eac Nanjing", 6 | "rt": [ 7 | { 8 | "ip": "43.137.75.107", 9 | "netmask": "255.255.255.255" 10 | }, 11 | { 12 | "ip": "119.45.28.76", 13 | "netmask": "255.255.255.255" 14 | }, 15 | { 16 | "ip": "175.27.136.54", 17 | "netmask": "255.255.255.255" 18 | }, 19 | { 20 | "ip": "146.56.195.241", 21 | "netmask": "255.255.255.255" 22 | }, 23 | { 24 | "ip": "43.137.36.164", 25 | "netmask": "255.255.255.255" 26 | }, 27 | { 28 | "ip": "118.195.151.176", 29 | "netmask": "255.255.255.255" 30 | }, 31 | { 32 | "ip": "1.13.173.29", 33 | "netmask": "255.255.255.255" 34 | }, 35 | { 36 | "ip": "118.195.145.56", 37 | "netmask": "255.255.255.255" 38 | } 39 | ], 40 | "rtt": [ 41 | { 42 | "family": "AF_INET", 43 | "ip": "43.137.75.107", 44 | "is_private": 0, 45 | "location": "43.137.75.107", 46 | "protocol": "ICMP" 47 | } 48 | ] 49 | } 50 | } -------------------------------------------------------------------------------- /Node/卡拉彼丘 Mudfish Custom Profiles/卡拉彼丘 成都 Chengdu.json: -------------------------------------------------------------------------------- 1 | { 2 | "item": { 3 | "category": "game", 4 | "icon": "", 5 | "name": "\u5361\u62c9\u5f7c\u4e18 \u6210\u90fd Chengdu", 6 | "rt": [ 7 | { 8 | "ip": "43.141.203.214", 9 | "netmask": "255.255.255.255" 10 | }, 11 | { 12 | "ip": "42.193.14.186", 13 | "netmask": "255.255.255.255" 14 | }, 15 | { 16 | "ip": "132.232.198.119", 17 | "netmask": "255.255.255.255" 18 | }, 19 | { 20 | "ip": "162.14.68.175", 21 | "netmask": "255.255.255.255" 22 | }, 23 | { 24 | "ip": "42.193.13.238", 25 | "netmask": "255.255.255.255" 26 | }, 27 | { 28 | "ip": "118.24.22.84", 29 | "netmask": "255.255.255.255" 30 | }, 31 | { 32 | "ip": "118.24.57.146", 33 | "netmask": "255.255.255.255" 34 | }, 35 | { 36 | "ip": "129.28.90.189", 37 | "netmask": "255.255.255.255" 38 | } 39 | ], 40 | "rtt": [ 41 | { 42 | "family": "AF_INET", 43 | "ip": "43.141.203.214", 44 | "is_private": 0, 45 | "location": "43.141.203.214", 46 | "protocol": "ICMP" 47 | } 48 | ] 49 | } 50 | } -------------------------------------------------------------------------------- /Node/卡拉彼丘 Mudfish Custom Profiles/卡拉彼丘 广州 Guangzhou.json: -------------------------------------------------------------------------------- 1 | { 2 | "item": { 3 | "category": "game", 4 | "icon": "", 5 | "name": "\u5361\u62c9\u5f7c\u4e18 \u5e7f\u5dde Guangzhou", 6 | "rt": [ 7 | { 8 | "ip": "119.91.241.217", 9 | "netmask": "255.255.255.255" 10 | }, 11 | { 12 | "ip": "129.204.166.68", 13 | "netmask": "255.255.255.255" 14 | }, 15 | { 16 | "ip": "114.132.155.237", 17 | "netmask": "255.255.255.255" 18 | }, 19 | { 20 | "ip": "42.193.226.174", 21 | "netmask": "255.255.255.255" 22 | }, 23 | { 24 | "ip": "43.138.139.109", 25 | "netmask": "255.255.255.255" 26 | }, 27 | { 28 | "ip": "159.75.93.60", 29 | "netmask": "255.255.255.255" 30 | }, 31 | { 32 | "ip": "81.71.156.229", 33 | "netmask": "255.255.255.255" 34 | }, 35 | { 36 | "ip": "119.91.211.81", 37 | "netmask": "255.255.255.255" 38 | } 39 | ], 40 | "rtt": [ 41 | { 42 | "family": "AF_INET", 43 | "ip": "119.91.241.217", 44 | "is_private": 0, 45 | "location": "119.91.241.217", 46 | "protocol": "ICMP" 47 | } 48 | ] 49 | } 50 | } -------------------------------------------------------------------------------- /CoreTests/LatencyChecker/UDPSessionTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Core.LatencyChecker; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Net; 9 | 10 | namespace Core.LatencyChecker.Tests 11 | { 12 | [TestClass()] 13 | public class UDPSessionTests 14 | { 15 | [TestMethod()] 16 | public async Task UDPSessionTest() 17 | { 18 | // Arrange 19 | var address = IPAddress.Parse("43.155.193.230"); 20 | var port = 20000; 21 | var latency = new List(); 22 | 23 | async Task LatencyAppend(float value) 24 | { 25 | latency.Add(value); 26 | await Task.CompletedTask; 27 | } 28 | 29 | var udpSession = new UDPSession(address, port, LatencyAppend); 30 | 31 | // Act 32 | udpSession.Start(); 33 | await Task.Delay(5000); 34 | udpSession.Stop(); 35 | 36 | // Assert 37 | Assert.IsTrue(latency.Average() > 0, "Average latency should be greater than 0."); 38 | Assert.IsTrue(latency.Average() < 1000, "Average latency should be less than 1000."); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /WpfApp/Views/MainWindowView.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /WpfApp/Views/RegionUserControl.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 19 | 23 |