Compare commits

...

27 Commits

Author SHA1 Message Date
Connection Refused
44da2e8011 Bump version to 1.8.3 2021-04-09 09:22:27 +08:00
Connection Refused
54daff70b3 Update build.ps1 2021-04-09 09:21:17 +08:00
Connection Refused
b218e785d8 Update build.ps1 2021-04-09 09:21:05 +08:00
Connection Refused
5b857cc518 Merge pull request #610 from NetchX/dependabot/nuget/Vanara.PInvoke.User32-3.3.8
Bump Vanara.PInvoke.User32 from 3.3.7 to 3.3.8
2021-04-08 22:59:04 +08:00
Connection Refused
4693025576 Merge pull request #609 from NetchX/dependabot/nuget/Vanara.PInvoke.IpHlpApi-3.3.8
Bump Vanara.PInvoke.IpHlpApi from 3.3.7 to 3.3.8
2021-04-08 22:58:55 +08:00
dependabot[bot]
46eefd3db9 Bump Vanara.PInvoke.User32 from 3.3.7 to 3.3.8
Bumps [Vanara.PInvoke.User32](https://github.com/dahall/vanara) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/dahall/vanara/releases)
- [Commits](https://github.com/dahall/vanara/compare/v3.3.7...v3.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-07 23:04:23 +00:00
dependabot[bot]
eb1ee9e820 Bump Vanara.PInvoke.IpHlpApi from 3.3.7 to 3.3.8
Bumps [Vanara.PInvoke.IpHlpApi](https://github.com/dahall/vanara) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/dahall/vanara/releases)
- [Commits](https://github.com/dahall/vanara/compare/v3.3.7...v3.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-07 23:04:15 +00:00
Connection Refused
b501ed38c4 Enable SelfContained 2021-04-05 02:16:48 +08:00
Connection Refused
6f1b0ee21f Merge remote-tracking branch 'refs/remotes/origin/master' 2021-04-05 02:11:19 +08:00
Connection Refused
ce6d96a779 Bump version to 1.8.3-Beta1145141919 2021-04-05 02:11:08 +08:00
Connection Refused
39f0f87b3a Update Netch.csproj 2021-04-05 02:09:39 +08:00
Connection Refused
642c4d1af8 Fix download.ps1 2021-04-05 02:04:50 +08:00
Connection Refused
d42aa8f184 Update build.ps1 2021-04-05 02:03:02 +08:00
Connection Refused
9c02ef353f Revert 2021-04-05 01:49:13 +08:00
ChsBuffer
1b4e7d41cc Update Netch.csproj: PostBuild 2021-04-04 21:59:43 +08:00
ChsBuffer
3d7dcbbffe Fix open links in about error 2021-04-04 21:59:41 +08:00
ChsBuffer
be9d7d6845 Update build script: exit when curl failed 2021-04-04 21:57:31 +08:00
ChsBuffer
a3620ed162 Normalize all the line endings 2021-04-02 13:58:45 +08:00
ChsBuffer
ba8c60675e Update download.ps1 2021-04-02 13:27:17 +08:00
ChsBuffer
c9a1265231 Update download.ps1 2021-04-02 13:06:21 +08:00
Connection Refused
92b030ebd9 Update release.yml 2021-04-02 08:53:30 +08:00
Connection Refused
7fd24d46d3 Update build.yml 2021-04-02 08:53:17 +08:00
Connection Refused
e2f6a58fde Update download.ps1 2021-04-02 08:50:22 +08:00
ChsBuffer
5f31109bcf Update SuffixVersion 2021-04-02 03:59:49 +08:00
Connection Refused
354608a72c Update README.md 2021-04-02 02:59:29 +08:00
Connection Refused
5803b94ae9 Update NativeMethods 2021-04-02 02:40:13 +08:00
Connection Refused
ee7c6aa608 Update .gitignore 2021-04-02 02:33:46 +08:00
80 changed files with 631 additions and 625 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
*.cs text

View File

@@ -1,4 +1,4 @@
name: Netch CI
name: Netch Build CI
on: [push, pull_request]
jobs:

View File

@@ -1,4 +1,4 @@
name: Netch CI
name: Netch Release CI
on:
push:
tags:

10
.gitignore vendored
View File

@@ -1,5 +1,5 @@
.vs/
.idea/
*/bin/
*/obj/
*.csproj.user
/.vs
/.vscode
/.idea
/release
/DataCache

View File

@@ -1,25 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.ActiveCfg = Debug|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.Build.0 = Debug|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.ActiveCfg = Release|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6EC9B043-ACA5-4BB9-96DB-493A2EF6E43F}
EndGlobalSection
EndGlobal
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.ActiveCfg = Debug|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.Build.0 = Debug|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.ActiveCfg = Release|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6EC9B043-ACA5-4BB9-96DB-493A2EF6E43F}
EndGlobalSection
EndGlobal

3
Netch/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/bin
/obj
/*.csproj.user

View File

@@ -1,3 +1,5 @@
using Netch.Models;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -7,15 +9,13 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Netch.Models;
using Netch.Utils;
using Timer = System.Timers.Timer;
namespace Netch.Controllers
{
public abstract class Guard
{
private readonly Timer _flushFileStreamTimer = new(300) {AutoReset = true};
private readonly Timer _flushFileStreamTimer = new(300) { AutoReset = true };
private FileStream? _logFileStream;

View File

@@ -1,9 +1,9 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using System;
using System.IO;
using System.Threading.Tasks;
namespace Netch.Controllers
{
@@ -58,13 +58,13 @@ namespace Netch.Controllers
Server = server;
Mode = mode;
// 刷新DNS缓存
NativeMethods.FlushDNSResolverCache();
// 刷新 DNS 缓存
NativeMethods.RefreshDNSCache();
if (DnsUtils.Lookup(server.Hostname) == null)
throw new MessageException(i18N.Translate("Lookup Server hostname failed"));
// 添加Netch到防火墙
// 添加 Netch 到防火墙
Firewall.AddNetchFwRules();
try
@@ -122,7 +122,7 @@ namespace Netch.Controllers
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName);
if (port != null)
TryReleaseTcpPort((ushort) port, portName);
TryReleaseTcpPort((ushort)port, portName);
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));

View File

@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using Netch.Interops;
using Netch.Interops;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using static Netch.Interops.RedirectorInterop;
namespace Netch.Controllers

View File

@@ -1,8 +1,8 @@
using System;
using Netch.Utils;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Netch.Utils;
namespace Netch.Controllers
{

View File

@@ -1,13 +1,13 @@
using System;
using Netch.Forms;
using Netch.Models;
using Netch.Servers.Socks5;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Netch.Forms;
using Netch.Models;
using Netch.Servers.Socks5;
namespace Netch.Controllers
{
@@ -17,7 +17,7 @@ namespace Netch.Controllers
public override string MainFile { get; protected set; } = "pcap2socks.exe";
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"└"};
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "└" };
private readonly OutboundAdapter _outbound = new();

View File

@@ -1,16 +1,14 @@
using System;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using Vanara.PInvoke;
using static Netch.Interops.TUNInterop;
using static Vanara.PInvoke.Ws2_32;
namespace Netch.Controllers
{
@@ -91,9 +89,9 @@ namespace Netch.Controllers
_tunAdapter = new TunAdapter();
NativeMethods.CreateUnicastIP((int) AddressFamily.InterNetwork,
NativeMethods.CreateUnicastIP(AddressFamily.InterNetwork,
Global.Settings.TUNTAP.Address,
Utils.Utils.SubnetToCidr(Global.Settings.TUNTAP.Netmask),
(byte)Utils.Utils.SubnetToCidr(Global.Settings.TUNTAP.Netmask),
_tunAdapter.InterfaceIndex);
SetupRouteTable(mode);
@@ -235,18 +233,18 @@ namespace Netch.Controllers
return false;
IAdapter adapter = routeType switch
{
RouteType.Outbound => _outboundAdapter,
RouteType.TUNTAP => _tunAdapter,
_ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null)
};
{
RouteType.Outbound => _outboundAdapter,
RouteType.TUNTAP => _tunAdapter,
_ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null)
};
List<string> ipList = routeType switch
{
RouteType.Outbound => _directIPs,
RouteType.TUNTAP => _proxyIPs,
_ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null)
};
{
RouteType.Outbound => _directIPs,
RouteType.TUNTAP => _proxyIPs,
_ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null)
};
string gateway = adapter.Gateway.ToString();
var index = adapter.InterfaceIndex;
@@ -257,13 +255,13 @@ namespace Netch.Controllers
switch (action)
{
case Action.Create:
result = NativeMethods.CreateRoute((int) AddressFamily.InterNetwork, ip, cidr, gateway, index, metric);
result = NativeMethods.CreateRoute(AddressFamily.InterNetwork, ip, (byte)cidr, gateway, index, metric);
if (result && record)
ipList.Add(ipNetwork);
break;
case Action.Delete:
result = NativeMethods.DeleteRoute((int) AddressFamily.InterNetwork, ip, cidr, gateway, index, metric);
result = NativeMethods.DeleteRoute(AddressFamily.InterNetwork, ip, (byte)cidr, gateway, index, metric);
break;
default:
throw new ArgumentOutOfRangeException(nameof(action), action, null);

View File

@@ -1,4 +1,6 @@
using System;
using Netch.Models.GitHubRelease;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
@@ -6,8 +8,6 @@ using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Netch.Models.GitHubRelease;
using Netch.Utils;
namespace Netch.Controllers
{
@@ -20,7 +20,7 @@ namespace Netch.Controllers
public const string Copyright = @"Copyright © 2019 - 2021";
public const string AssemblyVersion = @"1.8.3";
private const string Suffix = @"Beta114514";
private const string Suffix = @"";
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
@@ -46,7 +46,7 @@ namespace Netch.Controllers
var json = await WebUtil.DownloadStringAsync(WebUtil.CreateRequest(url));
var releases = JsonSerializer.Deserialize<List<Release>>(json)!;
LatestRelease = VersionUtil.GetLatestRelease(releases, isPreRelease);
LatestRelease = GetLatestRelease(releases, isPreRelease);
Global.Logger.Info($"Github 最新发布版本: {LatestRelease.tag_name}");
if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0)
{
@@ -104,5 +104,14 @@ namespace Netch.Controllers
return sb.ToString();
}
public static Release GetLatestRelease(IEnumerable<Release> releases, bool isPreRelease)
{
if (!isPreRelease)
releases = releases.Where(release => !release.prerelease);
var ordered = releases.OrderByDescending(release => release.tag_name, new VersionUtil.VersionComparer());
return ordered.ElementAt(0);
}
}
}
}

View File

@@ -1,8 +1,8 @@
using System;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Diagnostics;
using System.Windows.Forms;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms
{
@@ -21,17 +21,17 @@ namespace Netch.Forms
private void NetchPictureBox_Click(object sender, EventArgs e)
{
Process.Start("https://github.com/NetchX/Netch");
Utils.Utils.Open("https://github.com/NetchX/Netch");
}
private void ChannelLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Process.Start("https://t.me/Netch");
Utils.Utils.Open("https://t.me/Netch");
}
private void SponsorPictureBox_Click(object sender, EventArgs e)
{
Process.Start("https://www.mansora.co");
Utils.Utils.Open("https://www.mansora.co");
}
}
}

View File

@@ -1,9 +1,9 @@
using System;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms
{
@@ -54,7 +54,7 @@ namespace Netch.Forms
{
Global.Settings.TUNTAP.BypassIPs.Clear();
foreach (var ip in IPListBox.Items)
Global.Settings.TUNTAP.BypassIPs.Add((string) ip);
Global.Settings.TUNTAP.BypassIPs.Add((string)ip);
Configuration.Save();
MessageBoxX.Show(i18N.Translate("Saved"));

View File

@@ -1,3 +1,9 @@
using Microsoft.Win32;
using Netch.Controllers;
using Netch.Forms.Mode;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -8,12 +14,6 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;
using Netch.Controllers;
using Netch.Forms.Mode;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms
{
@@ -41,7 +41,7 @@ namespace Netch.Forms
#region i18N Translations
_mainFormText.Add(UninstallServiceToolStripMenuItem.Name, new[] {"Uninstall {0}", "NF Service"});
_mainFormText.Add(UninstallServiceToolStripMenuItem.Name, new[] { "Uninstall {0}", "NF Service" });
#endregion
@@ -63,7 +63,7 @@ namespace Netch.Forms
Text = i18N.TranslateFormat("Add [{0}] Server", fullName)
};
_mainFormText.Add(control.Name, new[] {"Add [{0}] Server", fullName});
_mainFormText.Add(control.Name, new[] { "Add [{0}] Server", fullName });
control.Click += AddServerToolStripMenuItem_Click;
ServerToolStripMenuItem.DropDownItems.Add(control);
}
@@ -184,7 +184,7 @@ namespace Netch.Forms
return string.Empty;
if (value is object[] values)
return i18N.TranslateFormat((string) values.First(), values.Skip(1).ToArray());
return i18N.TranslateFormat((string)values.First(), values.Skip(1).ToArray());
return i18N.Translate(value);
}
@@ -228,7 +228,7 @@ namespace Netch.Forms
throw new ArgumentNullException(nameof(sender));
// TODO get Util from Tag
var s = ((ToolStripMenuItem) sender).Text;
var s = ((ToolStripMenuItem)sender).Text;
var start = s.IndexOf("[", StringComparison.Ordinal) + 1;
var end = s.IndexOf("]", start, StringComparison.Ordinal);
@@ -348,7 +348,7 @@ namespace Netch.Forms
{
await Task.Run(() =>
{
NativeMethods.FlushDNSResolverCache();
NativeMethods.RefreshDNSCache();
DnsUtils.ClearCache();
});
@@ -704,7 +704,7 @@ namespace Netch.Forms
{
try
{
Global.Settings.ModeComboBoxSelectedIndex = Global.Modes.IndexOf((Models.Mode) ModeComboBox.SelectedItem);
Global.Settings.ModeComboBoxSelectedIndex = Global.Modes.IndexOf((Models.Mode)ModeComboBox.SelectedItem);
}
catch
{
@@ -721,7 +721,7 @@ namespace Netch.Forms
return;
}
var mode = (Models.Mode) ModeComboBox.SelectedItem;
var mode = (Models.Mode)ModeComboBox.SelectedItem;
if (ModifierKeys == Keys.Control)
{
Utils.Utils.Open(ModeHelper.GetFullPath(mode.RelativePath!));
@@ -756,7 +756,7 @@ namespace Netch.Forms
return;
}
ModeHelper.Delete((Models.Mode) ModeComboBox.SelectedItem);
ModeHelper.Delete((Models.Mode)ModeComboBox.SelectedItem);
SelectLastMode();
}
@@ -773,7 +773,7 @@ namespace Netch.Forms
{
// Clear
foreach (var button in ProfileTable.Controls)
((Button) button).Dispose();
((Button)button).Dispose();
ProfileTable.Controls.Clear();
ProfileTable.ColumnStyles.Clear();
@@ -799,7 +799,7 @@ namespace Netch.Forms
var columnCount = Global.Settings.ProfileTableColumnCount;
ProfileTable.ColumnCount = profileCount >= columnCount ? columnCount : profileCount;
ProfileTable.RowCount = (int) Math.Ceiling(profileCount / (float) columnCount);
ProfileTable.RowCount = (int)Math.Ceiling(profileCount / (float)columnCount);
for (var i = 0; i < profileCount; ++i)
{
@@ -848,8 +848,8 @@ namespace Netch.Forms
private Profile CreateProfileAtIndex(int index)
{
var server = (Server) ServerComboBox.SelectedItem;
var mode = (Models.Mode) ModeComboBox.SelectedItem;
var server = (Server)ServerComboBox.SelectedItem;
var mode = (Models.Mode)ModeComboBox.SelectedItem;
var name = ProfileNameText.Text;
Profile? profile;
@@ -866,8 +866,8 @@ namespace Netch.Forms
if (sender == null)
throw new ArgumentNullException(nameof(sender));
var profileButton = (Button) sender;
var profile = (Profile?) profileButton.Tag;
var profileButton = (Button)sender;
var profile = (Profile?)profileButton.Tag;
var index = ProfileTable.Controls.IndexOf(profileButton);
switch (ModifierKeys)
@@ -1107,13 +1107,13 @@ namespace Netch.Forms
{
NatTypeStatusLightLabel.Visible = Flags.IsWindows10Upper;
var c = natType switch
{
1 => Color.LimeGreen,
2 => Color.Yellow,
3 => Color.Red,
4 => Color.Black,
_ => throw new ArgumentOutOfRangeException(nameof(natType), natType, null)
};
{
1 => Color.LimeGreen,
2 => Color.Yellow,
3 => Color.Red,
4 => Color.Black,
_ => throw new ArgumentOutOfRangeException(nameof(natType), natType, null)
};
NatTypeStatusLightLabel.ForeColor = c;
}
@@ -1231,7 +1231,7 @@ namespace Netch.Forms
Configuration.Save();
}
foreach (var file in new[] {"data\\last.json", "data\\privoxy.conf"})
foreach (var file in new[] { "data\\last.json", "data\\privoxy.conf" })
if (File.Exists(file))
File.Delete(file);
@@ -1401,38 +1401,38 @@ namespace Netch.Forms
switch (cbx.Items[e.Index])
{
case Server item:
{
// 计算延迟底色
var numBoxBackBrush = item.Delay switch {> 200 => Brushes.Red, > 80 => Brushes.Yellow, >= 0 => _greenBrush, _ => Brushes.Gray};
{
// 计算延迟底色
var numBoxBackBrush = item.Delay switch { > 200 => Brushes.Red, > 80 => Brushes.Yellow, >= 0 => _greenBrush, _ => Brushes.Gray };
// 绘制延迟底色
e.Graphics.FillRectangle(numBoxBackBrush, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
// 绘制延迟底色
e.Graphics.FillRectangle(numBoxBackBrush, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
// 绘制延迟字符串
TextRenderer.DrawText(e.Graphics,
item.Delay.ToString(),
cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
// 绘制延迟字符串
TextRenderer.DrawText(e.Graphics,
item.Delay.ToString(),
cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
break;
}
break;
}
case Models.Mode item:
{
// 绘制 模式Box 底色
e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
{
// 绘制 模式Box 底色
e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
// 绘制 模式行数 字符串
TextRenderer.DrawText(e.Graphics,
item.Rule.Count.ToString(),
cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
// 绘制 模式行数 字符串
TextRenderer.DrawText(e.Graphics,
item.Rule.Count.ToString(),
cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
break;
}
break;
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Windows.Forms;
using Netch.Models;
using Netch.Models;
using Netch.Utils;
using System;
using System.Windows.Forms;
namespace Netch.Forms
{
@@ -23,20 +23,20 @@ namespace Netch.Forms
MessageBoxIcon msgIcon;
if (string.IsNullOrWhiteSpace(title))
title = level switch
{
LogLevel.INFO => "Information",
LogLevel.WARNING => "Warning",
LogLevel.ERROR => "Error",
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
};
{
LogLevel.INFO => "Information",
LogLevel.WARNING => "Warning",
LogLevel.ERROR => "Error",
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
};
msgIcon = level switch
{
LogLevel.INFO => MessageBoxIcon.Information,
LogLevel.WARNING => MessageBoxIcon.Warning,
LogLevel.ERROR => MessageBoxIcon.Exclamation,
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
};
{
LogLevel.INFO => MessageBoxIcon.Information,
LogLevel.WARNING => MessageBoxIcon.Warning,
LogLevel.ERROR => MessageBoxIcon.Exclamation,
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
};
return MessageBox.Show(owner, text, i18N.Translate(title), confirm ? MessageBoxButtons.OKCancel : MessageBoxButtons.OK, msgIcon);
}

View File

@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Microsoft.WindowsAPICodePack.Dialogs;
using Microsoft.WindowsAPICodePack.Dialogs;
using Netch.Controllers;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace Netch.Forms.Mode
{

View File

@@ -1,15 +1,15 @@
using System;
using System.IO;
using System.Windows.Forms;
using Netch.Models;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.IO;
using System.Windows.Forms;
namespace Netch.Forms.Mode
{
public partial class Route : Form
{
private readonly TagItem<int>[] _items = {new(1, "Proxy Rule IPs"), new(2, "Bypass Rule IPs")};
private readonly TagItem<int>[] _items = { new(1, "Proxy Rule IPs"), new(2, "Bypass Rule IPs") };
private readonly Models.Mode? _mode;
@@ -62,7 +62,7 @@ namespace Netch.Forms.Mode
_mode.Remark = RemarkTextBox.Text;
_mode.Rule.Clear();
_mode.Rule.AddRange(richTextBox1.Lines);
_mode.Type = (int) comboBox1.SelectedValue;
_mode.Type = (int)comboBox1.SelectedValue;
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
@@ -79,7 +79,7 @@ namespace Netch.Forms.Mode
var mode = new Models.Mode(fullName)
{
Type = (int) comboBox1.SelectedValue,
Type = (int)comboBox1.SelectedValue,
Remark = RemarkTextBox.Text
};

View File

@@ -1,13 +1,13 @@
#nullable disable
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms
{
@@ -38,13 +38,13 @@ namespace Netch.Forms
InitializeComponent();
_checkActions.Add(RemarkTextBox, s => true);
_saveActions.Add(RemarkTextBox, s => Server.Remark = (string) s);
_saveActions.Add(RemarkTextBox, s => Server.Remark = (string)s);
_checkActions.Add(AddressTextBox, s => s != string.Empty);
_saveActions.Add(AddressTextBox, s => Server.Hostname = (string) s);
_saveActions.Add(AddressTextBox, s => Server.Hostname = (string)s);
_checkActions.Add(PortTextBox, s => ushort.TryParse(s, out var port) && port != 0);
_saveActions.Add(PortTextBox, s => Server.Port = ushort.Parse((string) s));
_saveActions.Add(PortTextBox, s => Server.Port = ushort.Parse((string)s));
}
protected abstract string TypeName { get; }
@@ -99,7 +99,7 @@ namespace Netch.Forms
};
_checkActions.Add(textBox, check);
_saveActions.Add(textBox, o => save.Invoke((string) o));
_saveActions.Add(textBox, o => save.Invoke((string)o));
ConfigurationGroupBox.Controls.AddRange(new Control[]
{
textBox,
@@ -131,7 +131,7 @@ namespace Netch.Forms
comboBox.Items.AddRange(values.ToArray());
comboBox.SelectedIndex = values.IndexOf(value);
comboBox.DrawItem += Utils.Utils.DrawCenterComboBox;
_saveActions.Add(comboBox, o => save.Invoke((string) o));
_saveActions.Add(comboBox, o => save.Invoke((string)o));
ConfigurationGroupBox.Controls.AddRange(new Control[]
{
comboBox,
@@ -159,7 +159,7 @@ namespace Netch.Forms
Text = remark
};
_saveActions.Add(checkBox, o => save.Invoke((bool) o));
_saveActions.Add(checkBox, o => save.Invoke((bool)o));
ConfigurationGroupBox.Controls.AddRange(new Control[]
{
checkBox

View File

@@ -1,3 +1,6 @@
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
@@ -5,9 +8,6 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms
{
@@ -37,7 +37,7 @@ namespace Netch.Forms
BindCheckBox(AllowDevicesCheckBox,
c => Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1",
Global.Settings.LocalAddress switch {"127.0.0.1" => false, "0.0.0.0" => true, _ => false});
Global.Settings.LocalAddress switch { "127.0.0.1" => false, "0.0.0.0" => true, _ => false });
BindCheckBox(ResolveServerHostnameCheckBox, c => Global.Settings.ResolveServerHostname = c, Global.Settings.ResolveServerHostname);
@@ -116,7 +116,7 @@ namespace Netch.Forms
Global.Settings.Redirector.ChildProcessHandle);
BindListComboBox(ProcessProxyProtocolComboBox,
s => Global.Settings.Redirector.ProxyProtocol = (PortType) Enum.Parse(typeof(PortType), s.ToString(), false),
s => Global.Settings.Redirector.ProxyProtocol = (PortType)Enum.Parse(typeof(PortType), s.ToString(), false),
Enum.GetNames(typeof(PortType)),
Global.Settings.Redirector.ProxyProtocol.ToString());
@@ -284,7 +284,7 @@ namespace Netch.Forms
{
try
{
return check.Invoke((T) Convert.ChangeType(s, typeof(T)));
return check.Invoke((T)Convert.ChangeType(s, typeof(T)));
}
catch
{
@@ -292,19 +292,19 @@ namespace Netch.Forms
}
});
_saveActions.Add(control, c => save.Invoke((T) Convert.ChangeType(((TextBox) c).Text, typeof(T))));
_saveActions.Add(control, c => save.Invoke((T)Convert.ChangeType(((TextBox)c).Text, typeof(T))));
}
private void BindCheckBox(CheckBox control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((CheckBox) c).Checked));
_saveActions.Add(control, c => save.Invoke(((CheckBox)c).Checked));
}
private void BindRadioBox(RadioButton control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((RadioButton) c).Checked));
_saveActions.Add(control, c => save.Invoke(((RadioButton)c).Checked));
}
private void BindListComboBox<T>(ComboBox comboBox, Action<T> save, IEnumerable<T> values, T value) where T : notnull
@@ -318,7 +318,7 @@ namespace Netch.Forms
comboBox.ValueMember = nameof(TagItem<T>.Value);
comboBox.DisplayMember = nameof(TagItem<T>.Text);
_saveActions.Add(comboBox, c => save.Invoke(((TagItem<T>) ((ComboBox) c).SelectedItem).Value));
_saveActions.Add(comboBox, c => save.Invoke(((TagItem<T>)((ComboBox)c).SelectedItem).Value));
Load += (_, _) => { comboBox.SelectedItem = tagItems.SingleOrDefault(t => t.Value.Equals(value)); };
}
@@ -327,7 +327,7 @@ namespace Netch.Forms
if (values != null)
control.Items.AddRange(values);
_saveActions.Add(control, c => save.Invoke(((ComboBox) c).Text));
_saveActions.Add(control, c => save.Invoke(((ComboBox)c).Text));
_checkActions.Add(control, check.Invoke);
Load += (_, _) => { control.Text = value; };

View File

@@ -1,9 +1,9 @@
using System;
using System.Linq;
using System.Windows.Forms;
using Netch.Models;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Linq;
using System.Windows.Forms;
namespace Netch.Forms
{

View File

@@ -1,12 +1,12 @@
using Netch.Forms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Loggers;
using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Windows.Forms;
using Netch.Forms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Loggers;
namespace Netch
{

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace Netch.Interops
{

View File

@@ -1,5 +1,4 @@
using System.Runtime.InteropServices;
using Netch.Utils;
namespace Netch.Interops
{
@@ -57,7 +56,7 @@ namespace Netch.Interops
return aio_free();
}
public const int UdpNameListOffset = (int) NameList.TYPE_UDPLISN - (int) NameList.TYPE_TCPLISN;
public const int UdpNameListOffset = (int)NameList.TYPE_UDPLISN - (int)NameList.TYPE_TCPLISN;
private const string Redirector_bin = "Redirector.bin";

View File

@@ -1,6 +1,5 @@
using System.Runtime.InteropServices;
using System.Text;
using Netch.Utils;
namespace Netch.Interops
{

View File

@@ -1,5 +1,6 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace Netch.Models.GitHubRelease
{
@@ -8,28 +9,53 @@ namespace Netch.Models.GitHubRelease
{
public Version Version { get; }
public string Suffix { get; }
public string? Suffix { get; }
public SuffixVersion(Version version, string suffix)
public int SuffixNum { get; }
private SuffixVersion(Version version)
{
Version = version;
Suffix = null;
SuffixNum = 0;
}
private SuffixVersion(Version version, string suffix, int suffixNum)
{
Version = version;
Suffix = suffix;
SuffixNum = suffixNum;
}
public static SuffixVersion Parse(string? input)
public static SuffixVersion Parse(string? value)
{
if (input == null)
throw new ArgumentNullException(nameof(input));
if (value == null)
throw new ArgumentNullException(nameof(value));
var split = input.Split('-');
var dotNetVersion = Version.Parse(split[0]);
var preRelease = split.ElementAtOrDefault(1) ?? string.Empty;
var strings = value.Split('-');
return new SuffixVersion(dotNetVersion, preRelease);
var version = Version.Parse(strings[0]);
var suffix = strings.ElementAtOrDefault(1)?.Trim();
switch (suffix)
{
case null:
return new SuffixVersion(version);
case "":
throw new Exception("suffix WhiteSpace");
default:
{
var match = Regex.Match(suffix, @"(?<suffix>\D+)(?<num>\d+)");
if (!match.Success)
throw new Exception();
return new SuffixVersion(version, match.Groups["suffix"].Value, int.Parse(match.Groups["num"].Value));
}
}
}
public static bool TryParse(string input, out SuffixVersion result)
public static bool TryParse(string? input, out SuffixVersion result)
{
result = default;
try
{
result = Parse(input);
@@ -37,7 +63,6 @@ namespace Netch.Models.GitHubRelease
}
catch (Exception)
{
result = default;
return false;
}
}
@@ -62,21 +87,22 @@ namespace Netch.Models.GitHubRelease
if (versionComparison != 0)
return versionComparison;
if (Suffix == string.Empty)
return other.Suffix == string.Empty ? 0 : 1;
if (other.Suffix == string.Empty)
return -1;
var suffixExistComparison = (Suffix != null ? 1 : 0) - (other.Suffix != null ? 1 : 0);
if (suffixExistComparison != 0)
return suffixExistComparison;
var suffixComparison = string.Compare(Suffix, other.Suffix, StringComparison.OrdinalIgnoreCase);
return suffixComparison;
if (suffixComparison != 0)
return suffixComparison;
return SuffixNum - other.SuffixNum;
}
public override string ToString()
{
var s = Version.ToString();
if (Suffix != string.Empty)
s += $"-{Suffix}";
if (Suffix != null)
s += $"-{Suffix}{SuffixNum}";
return s;
}

View File

@@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
namespace Netch.Models.GitHubRelease
{
public class VersionComparer : IComparer<object>
{
public int Compare(object? x, object? y)
{
if (x == null)
throw new ArgumentNullException(nameof(x));
if (y == null)
throw new ArgumentNullException(nameof(y));
return VersionUtil.CompareVersion(x.ToString(), y.ToString());
}
}
}

View File

@@ -1,33 +1,37 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Netch.Models.GitHubRelease
{
public static class VersionUtil
{
public static Release GetLatestRelease(IEnumerable<Release> releases, bool isPreRelease)
{
if (!isPreRelease)
releases = releases.Where(release => !release.prerelease);
private static VersionComparer instance = new();
releases = releases.Where(release => IsVersionString(release.tag_name));
var ordered = releases.OrderByDescending(release => release.tag_name, new VersionComparer());
return ordered.ElementAt(0);
public static int CompareVersion(string x, string y)
{
return instance.Compare(x, y);
}
private static bool IsVersionString(string str)
public class VersionComparer : IComparer<string>
{
return SuffixVersion.TryParse(str, out _);
}
/// <summary>
/// Greater than 0 newer
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public int Compare(string? x, string? y)
{
var xResult = SuffixVersion.TryParse(x, out var version1) ? 1 : 0;
var yResult = SuffixVersion.TryParse(y, out var version2) ? 1 : 0;
/// <returns> =0:versions are equal</returns>
/// <returns> &gt;0:version1 is greater</returns>
/// <returns> &lt;0:version2 is greater</returns>
public static int CompareVersion(string? v1, string? v2)
{
var version1 = SuffixVersion.Parse(v1);
var version2 = SuffixVersion.Parse(v2);
return version1.CompareTo(version2);
var parseResult = xResult - yResult;
if (parseResult != 0)
return parseResult;
return version1.CompareTo(version2);
}
}
}
}

View File

@@ -5,7 +5,7 @@ namespace Netch.Models
{
public interface IAdapter
{
int InterfaceIndex { get; }
ulong InterfaceIndex { get; }
IPAddress Gateway { get; }

View File

@@ -1,6 +1,6 @@
using System;
using Netch.Controllers;
using System;
using System.Collections.Generic;
using Netch.Controllers;
namespace Netch.Models
{

View File

@@ -1,5 +1,5 @@
using System;
using Netch.Interfaces;
using Netch.Interfaces;
using System;
namespace Netch.Models.Loggers
{

View File

@@ -1,12 +1,12 @@
using System;
using Netch.Interfaces;
using System;
using System.IO;
using Netch.Interfaces;
namespace Netch.Models.Loggers
{
public class FileLogger : ILogger
{
public string LogFile { get; set; }= Path.Combine(Global.NetchDir, "logging\\application.log");
public string LogFile { get; set; } = Path.Combine(Global.NetchDir, "logging\\application.log");
private readonly object _fileLock = new();

View File

@@ -1,9 +1,9 @@
using System;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Netch.Utils;
namespace Netch.Models
{

View File

@@ -2,7 +2,6 @@
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using Netch.Utils;
using Vanara.PInvoke;
namespace Netch.Models
@@ -22,7 +21,7 @@ namespace Netch.Models
ni.GetIPProperties().GetIPv4Properties().Index == pRoute.dwForwardIfIndex);
Address = new IPAddress(pRoute.dwForwardNextHop.S_addr);
InterfaceIndex = (int) pRoute.dwForwardIfIndex;
InterfaceIndex = (ulong)pRoute.dwForwardIfIndex;
Gateway = new IPAddress(pRoute.dwForwardNextHop.S_un_b);
Global.Logger.Info($"出口 网关 地址:{Gateway}");
@@ -34,7 +33,7 @@ namespace Netch.Models
/// <summary>
/// 索引
/// </summary>
public int InterfaceIndex { get; }
public ulong InterfaceIndex { get; }
/// <summary>
/// 网关

View File

@@ -1,8 +1,8 @@
using System;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Netch.Utils;
namespace Netch.Models
{

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Netch.Utils;
using Netch.Utils;
using System.Collections.Generic;
namespace Netch.Models
{
@@ -265,7 +265,7 @@ namespace Netch.Models
public Setting Clone()
{
return (Setting) MemberwiseClone();
return (Setting)MemberwiseClone();
}
public void Set(Setting value)

View File

@@ -1,6 +1,6 @@
using Netch.Utils;
using System.Collections.Generic;
using System.Linq;
using Netch.Utils;
namespace Netch.Models
{

View File

@@ -1,8 +1,7 @@
using System.Linq;
using Netch.Interops;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using Netch.Interops;
using Netch.Utils;
namespace Netch.Models
{
@@ -10,18 +9,18 @@ namespace Netch.Models
{
public TunAdapter()
{
InterfaceIndex = (int) NativeMethods.ConvertLuidToIndex(TUNInterop.tun_luid());
NetworkInterface = NetworkInterface.GetAllNetworkInterfaces().First(i => i.GetIPProperties().GetIPv4Properties().Index == InterfaceIndex);
InterfaceIndex = NativeMethods.ConvertLuidToIndex(TUNInterop.tun_luid());
NetworkInterface = NetworkInterface.GetAllNetworkInterfaces().First(i => i.GetIPProperties().GetIPv4Properties().Index == (int)InterfaceIndex);
Gateway = IPAddress.Parse(Global.Settings.TUNTAP.Gateway);
Global.Logger.Info($"WinTUN 适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {InterfaceIndex}");
}
public int InterfaceIndex { get; }
public ulong InterfaceIndex { get; }
public IPAddress Gateway { get; }
public NetworkInterface NetworkInterface { get; }
}
}
}

View File

@@ -1,50 +1,29 @@
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Netch
{
public static class NativeMethods
{
/// <summary>
/// 分配 IP 地址
/// </summary>
/// <param name="inet">AF_INET / AF_INET6</param>
/// <param name="address">目标地址</param>
/// <param name="cidr">CIDR</param>
/// <param name="index">适配器索引</param>
/// <returns>是否成功</returns>
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl, EntryPoint = "CreateUnicastIP")]
public static extern bool CreateUnicastIP(int inet, string address, int cidr, int index);
/// <summary>
/// 创建路由规则
/// </summary>
/// <param name="inet">AF_INET / AF_INET6</param>
/// <param name="address">目标地址</param>
/// <param name="cidr">CIDR</param>
/// <param name="gateway">网关地址</param>
/// <param name="index">适配器索引</param>
/// <param name="metric">跃点数</param>
/// <returns>是否成功</returns>
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl, EntryPoint = "CreateRoute")]
public static extern bool CreateRoute(int inet, string address, int cidr, string gateway, int index, int metric = 0);
/// <summary>
/// 删除路由规则
/// </summary>
/// <param name="inet">AF_INET / AF_INET6</param>
/// <param name="address">目标地址</param>
/// <param name="cidr">掩码地址</param>
/// <param name="gateway">网关地址</param>
/// <param name="index">适配器索引</param>
/// <param name="metric">跃点数</param>
/// <returns>是否成功</returns>
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeleteRoute")]
public static extern bool DeleteRoute(int inet, string address, int cidr, string gateway, int index, int metric = 0);
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
public static extern uint RefreshDNSCache();
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern ulong ConvertLuidToIndex(ulong luid);
public static extern ulong ConvertLuidToIndex(ulong id);
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
public static extern uint FlushDNSResolverCache();
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CreateIPv4(string address, string netmask, ulong index);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CreateUnicastIP(AddressFamily inet, string address, byte cidr, ulong index);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool RefreshIPTable(AddressFamily inet, ulong index);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CreateRoute(AddressFamily inet, string address, byte cidr, string gateway, ulong index, int metric);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool DeleteRoute(AddressFamily inet, string address, byte cidr, string gateway, ulong index, int metric);
}
}
}

View File

@@ -1,13 +1,13 @@
using System;
using Netch.Controllers;
using Netch.Forms;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Netch.Controllers;
using Netch.Forms;
using Netch.Utils;
using static Vanara.PInvoke.Kernel32;
namespace Netch
@@ -41,7 +41,7 @@ namespace Netch
Updater.Updater.CleanOld(Global.NetchDir);
// 预创建目录
var directories = new[] {"mode\\Custom", "data", "i18n", "logging"};
var directories = new[] { "mode\\Custom", "data", "i18n", "logging" };
foreach (var item in directories)
if (!Directory.Exists(item))
Directory.CreateDirectory(item);

View File

@@ -1,5 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<UseWindowsForms>true</UseWindowsForms>
@@ -46,25 +45,14 @@
</PackageReference>
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<PackageReference Include="TaskScheduler" Version="2.9.1" />
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.3.7" />
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.3.8" />
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.4" />
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.7" />
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.8" />
<PackageReference Include="WindowsFirewallHelper" Version="2.0.4.70-beta2" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="5.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<None Remove=".gitignore" />
<None Visible="false" Include="..\binaries\**" LinkBase="bin" CopyToPublishDirectory="PreserveNewest" CopyToOutputDirectory="PreserveNewest" />
<None Update="..\binaries\NTT.exe">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</None>
<None Remove="..\binaries\.git" />
<None Visible="false" Include="..\translations\i18n\**" LinkBase="i18n" CopyToPublishDirectory="PreserveNewest" CopyToOutputDirectory="PreserveNewest" />
<None Visible="false" Include="..\modes\mode\**" LinkBase="mode" CopyToPublishDirectory="PreserveNewest" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
@@ -100,5 +88,4 @@
<_FilesToBundle Remove="$(PkgMicrosoft_Diagnostics_Tracing_TraceEvent)\lib\netstandard1.6\TraceReloggerLib.dll" />
</ItemGroup>
</Target>
</Project>

View File

@@ -1,6 +1,6 @@
using System.Reflection;
using Netch.Controllers;
using System.Reflection;
using System.Runtime.InteropServices;
using Netch.Controllers;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Netch.Controllers;
using Netch.Models;
using System.Collections.Generic;
namespace Netch.Servers.Shadowsocks
{
@@ -8,9 +8,9 @@ namespace Netch.Servers.Shadowsocks
{
public override string MainFile { get; protected set; } = "Shadowsocks.exe";
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"listening at"};
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "listening at" };
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] {"Invalid config path", "usage", "plugin service exit unexpectedly"};
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] { "Invalid config path", "usage", "plugin service exit unexpectedly" };
public override string Name { get; } = "Shadowsocks";
@@ -20,7 +20,7 @@ namespace Netch.Servers.Shadowsocks
public void Start(in Server s, in Mode mode)
{
var server = (Shadowsocks) s;
var server = (Shadowsocks)s;
var command = new SSParameter
{

View File

@@ -1,14 +1,14 @@
using System;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Shadowsocks.Form;
using Netch.Servers.Shadowsocks.Models.SSD;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Web;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Shadowsocks.Form;
using Netch.Servers.Shadowsocks.Models.SSD;
using Netch.Utils;
namespace Netch.Servers.Shadowsocks
{
@@ -22,13 +22,13 @@ namespace Netch.Servers.Shadowsocks
public string ShortName { get; } = "SS";
public string[] UriScheme { get; } = {"ss", "ssd"};
public string[] UriScheme { get; } = { "ss", "ssd" };
public Type ServerType { get; } = typeof(Shadowsocks);
public void Edit(Server s)
{
new ShadowsocksForm((Shadowsocks) s).ShowDialog();
new ShadowsocksForm((Shadowsocks)s).ShowDialog();
}
public void Create()
@@ -38,7 +38,7 @@ namespace Netch.Servers.Shadowsocks
public string GetShareLink(Server s)
{
var server = (Shadowsocks) s;
var server = (Shadowsocks)s;
// ss://method:password@server:port#Remark
return "ss://" + ShareLink.URLSafeBase64Encode($"{server.EncryptMethod}:{server.Password}@{server.Hostname}:{server.Port}") + "#" +
HttpUtility.UrlEncode(server.Remark);
@@ -52,7 +52,7 @@ namespace Netch.Servers.Shadowsocks
public IEnumerable<Server> ParseUri(string text)
{
if (text.StartsWith("ss://"))
return new[] {ParseSsUri(text)};
return new[] { ParseSsUri(text) };
if (text.StartsWith("ssd://"))
return ParseSsdUri(text);
@@ -62,7 +62,7 @@ namespace Netch.Servers.Shadowsocks
public bool CheckServer(Server s)
{
var server = (Shadowsocks) s;
var server = (Shadowsocks)s;
if (!SSGlobal.EncryptMethods.Contains(server.EncryptMethod))
{
Global.Logger.Error($"不支持的 SS 加密方式:{server.EncryptMethod}");
@@ -79,17 +79,17 @@ namespace Netch.Servers.Shadowsocks
var json = JsonSerializer.Deserialize<Main>(ShareLink.URLSafeBase64Decode(s.Substring(6)))!;
return json.servers.Select(server => new Shadowsocks
{
Remark = server.remarks,
Hostname = server.server,
Port = server.port != 0 ? server.port : json.port,
Password = server.password ?? json.password,
EncryptMethod = server.encryption ?? json.encryption,
Plugin = string.IsNullOrEmpty(json.plugin) ? string.IsNullOrEmpty(server.plugin) ? null : server.plugin : json.plugin,
PluginOption = string.IsNullOrEmpty(json.plugin_options)
{
Remark = server.remarks,
Hostname = server.server,
Port = server.port != 0 ? server.port : json.port,
Password = server.password ?? json.password,
EncryptMethod = server.encryption ?? json.encryption,
Plugin = string.IsNullOrEmpty(json.plugin) ? string.IsNullOrEmpty(server.plugin) ? null : server.plugin : json.plugin,
PluginOption = string.IsNullOrEmpty(json.plugin_options)
? string.IsNullOrEmpty(server.plugin_options) ? null : server.plugin_options
: json.plugin_options
})
})
.Where(CheckServer);
}

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Netch.Models;
using Netch.Models;
using System.Collections.Generic;
namespace Netch.Servers.Shadowsocks
{

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Netch.Controllers;
using Netch.Models;
using System.Collections.Generic;
namespace Netch.Servers.ShadowsocksR
{
@@ -8,9 +8,9 @@ namespace Netch.Servers.ShadowsocksR
{
public override string MainFile { get; protected set; } = "ShadowsocksR.exe";
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"listening at"};
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "listening at" };
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] {"Invalid config path", "usage"};
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] { "Invalid config path", "usage" };
public override string Name { get; } = "ShadowsocksR";
@@ -20,7 +20,7 @@ namespace Netch.Servers.ShadowsocksR
public void Start(in Server s, in Mode mode)
{
var server = (ShadowsocksR) s;
var server = (ShadowsocksR)s;
var command = new SSRParameter
{

View File

@@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Netch.Controllers;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.ShadowsocksR.Form;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Netch.Servers.ShadowsocksR
{
@@ -19,13 +19,13 @@ namespace Netch.Servers.ShadowsocksR
public string ShortName { get; } = "SR";
public string[] UriScheme { get; } = {"ssr"};
public string[] UriScheme { get; } = { "ssr" };
public Type ServerType { get; } = typeof(ShadowsocksR);
public void Edit(Server s)
{
new ShadowsocksRForm((ShadowsocksR) s).ShowDialog();
new ShadowsocksRForm((ShadowsocksR)s).ShowDialog();
}
public void Create()
@@ -35,7 +35,7 @@ namespace Netch.Servers.ShadowsocksR
public string GetShareLink(Server s)
{
var server = (ShadowsocksR) s;
var server = (ShadowsocksR)s;
// https://github.com/shadowsocksr-backup/shadowsocks-rss/wiki/SSR-QRcode-scheme
// ssr://base64(host:port:protocol:method:obfs:base64pass/?obfsparam=base64param&protoparam=base64param&remarks=base64remarks&group=base64group&udpport=0&uot=0)
@@ -143,7 +143,7 @@ namespace Netch.Servers.ShadowsocksR
public bool CheckServer(Server s)
{
var server = (ShadowsocksR) s;
var server = (ShadowsocksR)s;
if (!SSRGlobal.EncryptMethods.Contains(server.EncryptMethod))
{
Global.Logger.Error($"不支持的 SSR 加密方式:{server.EncryptMethod}");

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Netch.Models;
using Netch.Models;
using System.Collections.Generic;
namespace Netch.Servers.ShadowsocksR
{

View File

@@ -9,7 +9,7 @@ namespace Netch.Servers.Socks5
public override void Start(in Server s, in Mode mode)
{
var server = (Socks5) s;
var server = (Socks5)s;
if (server.Auth())
base.Start(s, mode);
}

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Netch.Controllers;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Socks5.Form;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Netch.Servers.Socks5
{
@@ -23,7 +23,7 @@ namespace Netch.Servers.Socks5
public void Edit(Server s)
{
new Socks5Form((Socks5) s).ShowDialog();
new Socks5Form((Socks5)s).ShowDialog();
}
public void Create()
@@ -33,7 +33,7 @@ namespace Netch.Servers.Socks5
public string GetShareLink(Server s)
{
var server = (Socks5) s;
var server = (Socks5)s;
// https://t.me/socks?server=1.1.1.1&port=443
return $"https://t.me/socks?server={server.Hostname}&port={server.Port}" +
$"{(!string.IsNullOrWhiteSpace(server.Username) ? $"&user={server.Username}" : "")}" +
@@ -68,7 +68,7 @@ namespace Netch.Servers.Socks5
if (dict.ContainsKey("pass") && !string.IsNullOrWhiteSpace(dict["pass"]))
data.Password = dict["pass"];
return new[] {data};
return new[] { data };
}
public bool CheckServer(Server s)

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using Netch.Controllers;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Trojan.Models;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
namespace Netch.Servers.Trojan
{
@@ -11,9 +11,9 @@ namespace Netch.Servers.Trojan
{
public override string MainFile { get; protected set; } = "Trojan.exe";
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"started"};
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "started" };
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] {"exiting"};
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] { "exiting" };
public override string Name { get; } = "Trojan";
@@ -23,7 +23,7 @@ namespace Netch.Servers.Trojan
public void Start(in Server s, in Mode mode)
{
var server = (Trojan) s;
var server = (Trojan)s;
var trojanConfig = new TrojanConfig
{
local_addr = this.LocalAddress(),

View File

@@ -1,10 +1,10 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Trojan.Form;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Trojan.Form;
namespace Netch.Servers.Trojan
{
@@ -18,13 +18,13 @@ namespace Netch.Servers.Trojan
public string ShortName { get; } = "TR";
public string[] UriScheme { get; } = {"trojan"};
public string[] UriScheme { get; } = { "trojan" };
public Type ServerType { get; } = typeof(Trojan);
public void Edit(Server s)
{
new TrojanForm((Trojan) s).ShowDialog();
new TrojanForm((Trojan)s).ShowDialog();
}
public void Create()
@@ -34,7 +34,7 @@ namespace Netch.Servers.Trojan
public string GetShareLink(Server s)
{
var server = (Trojan) s;
var server = (Trojan)s;
return $"trojan://{HttpUtility.UrlEncode(server.Password)}@{server.Hostname}:{server.Port}#{server.Remark}";
}
@@ -79,7 +79,7 @@ namespace Netch.Servers.Trojan
data.Hostname = match.Groups["server"].Value;
data.Port = ushort.Parse(match.Groups["port"].Value);
return new[] {data};
return new[] { data };
}
public bool CheckServer(Server s)

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
using Netch.Models;
using Netch.Servers.V2ray.Models;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Netch.Models;
using Netch.Servers.V2ray.Models;
using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig;
namespace Netch.Servers.V2ray.Utils
@@ -109,8 +109,8 @@ namespace Netch.Servers.V2ray.Utils
switch (server)
{
case Socks5.Socks5 socks5:
{
outbound.settings.servers = new List<ServersItem>
{
outbound.settings.servers = new List<ServersItem>
{
new()
{
@@ -130,80 +130,80 @@ namespace Netch.Servers.V2ray.Utils
}
};
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
outbound.protocol = "socks";
break;
}
case VLESS.VLESS vless:
{
var vnextItem = new VnextItem
{
users = new List<UsersItem>(),
address = server.AutoResolveHostname(),
port = server.Port
};
outbound.settings.vnext = new List<VnextItem> {vnextItem};
var usersItem = new UsersItem
{
id = vless.UserID,
alterId = 0,
flow = string.Empty,
encryption = vless.EncryptMethod
};
vnextItem.users.Add(usersItem);
var streamSettings = outbound.streamSettings;
boundStreamSettings(vless, ref streamSettings);
if (vless.TLSSecureType == "xtls")
{
usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow;
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
outbound.protocol = "socks";
break;
}
else
case VLESS.VLESS vless:
{
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
}
var vnextItem = new VnextItem
{
users = new List<UsersItem>(),
address = server.AutoResolveHostname(),
port = server.Port
};
outbound.protocol = "vless";
outbound.settings.servers = null;
break;
}
outbound.settings.vnext = new List<VnextItem> { vnextItem };
var usersItem = new UsersItem
{
id = vless.UserID,
alterId = 0,
flow = string.Empty,
encryption = vless.EncryptMethod
};
vnextItem.users.Add(usersItem);
var streamSettings = outbound.streamSettings;
boundStreamSettings(vless, ref streamSettings);
if (vless.TLSSecureType == "xtls")
{
usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow;
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
}
else
{
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
}
outbound.protocol = "vless";
outbound.settings.servers = null;
break;
}
case VMess.VMess vmess:
{
var vnextItem = new VnextItem
{
users = new List<UsersItem>(),
address = server.AutoResolveHostname(),
port = server.Port
};
var vnextItem = new VnextItem
{
users = new List<UsersItem>(),
address = server.AutoResolveHostname(),
port = server.Port
};
outbound.settings.vnext = new List<VnextItem> {vnextItem};
outbound.settings.vnext = new List<VnextItem> { vnextItem };
var usersItem = new UsersItem
{
id = vmess.UserID,
alterId = vmess.AlterID,
security = vmess.EncryptMethod
};
var usersItem = new UsersItem
{
id = vmess.UserID,
alterId = vmess.AlterID,
security = vmess.EncryptMethod
};
vnextItem.users.Add(usersItem);
vnextItem.users.Add(usersItem);
var streamSettings = outbound.streamSettings;
boundStreamSettings(vmess, ref streamSettings);
var streamSettings = outbound.streamSettings;
boundStreamSettings(vmess, ref streamSettings);
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
outbound.protocol = "vmess";
break;
}
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
outbound.protocol = "vmess";
break;
}
}
v2rayConfig.outbounds.AddRange(new[]
@@ -274,7 +274,7 @@ namespace Netch.Servers.V2ray.Utils
case "ws":
var wsSettings = new WsSettings
{
headers = !string.IsNullOrWhiteSpace(server.Host) ? new Headers {Host = server.Host} : null,
headers = !string.IsNullOrWhiteSpace(server.Host) ? new Headers { Host = server.Host } : null,
path = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
};

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
using System.IO;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.V2ray.Utils;
using System.Collections.Generic;
using System.IO;
namespace Netch.Servers.V2ray
{
@@ -10,9 +10,9 @@ namespace Netch.Servers.V2ray
{
public override string MainFile { get; protected set; } = "xray.exe";
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"started"};
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "started" };
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] {"config file not readable", "failed to"};
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] { "config file not readable", "failed to" };
public override string Name { get; } = "Xray";

View File

@@ -1,10 +1,10 @@
using Netch.Models;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using Netch.Models;
using Netch.Utils;
namespace Netch.Servers.V2ray
{
@@ -13,7 +13,7 @@ namespace Netch.Servers.V2ray
public static IEnumerable<Server> ParseVUri(string text)
{
var scheme = ShareLink.GetUriScheme(text).ToLower();
var server = scheme switch {"vmess" => new VMess.VMess(), "vless" => new VLESS.VLESS(), _ => throw new ArgumentOutOfRangeException()};
var server = scheme switch { "vmess" => new VMess.VMess(), "vless" => new VLESS.VLESS(), _ => throw new ArgumentOutOfRangeException() };
if (text.Contains("#"))
{
server.Remark = Uri.UnescapeDataString(text.Split('#')[1]);
@@ -25,7 +25,7 @@ namespace Netch.Servers.V2ray
var parameter = HttpUtility.ParseQueryString(text.Split('?')[1]);
text = text.Substring(0, text.IndexOf("?", StringComparison.Ordinal));
server.TransferProtocol = parameter.Get("type") ?? "tcp";
server.EncryptMethod = parameter.Get("encryption") ?? scheme switch {"vless" => "none", _ => "auto"};
server.EncryptMethod = parameter.Get("encryption") ?? scheme switch { "vless" => "none", _ => "auto" };
switch (server.TransferProtocol)
{
case "tcp":
@@ -54,7 +54,7 @@ namespace Netch.Servers.V2ray
{
server.Host = parameter.Get("sni") ?? "";
if (server.TLSSecureType == "xtls")
((VLESS.VLESS) server).Flow = parameter.Get("flow") ?? "";
((VLESS.VLESS)server).Flow = parameter.Get("flow") ?? "";
}
}
@@ -67,13 +67,13 @@ namespace Netch.Servers.V2ray
server.Hostname = match.Groups["server"].Value;
server.Port = ushort.Parse(match.Groups["port"].Value);
return new[] {server};
return new[] { server };
}
public static string GetVShareLink(Server s, string scheme = "vmess")
{
// https://github.com/XTLS/Xray-core/issues/91
var server = (VMess.VMess) s;
var server = (VMess.VMess)s;
var parameter = new Dictionary<string, string>();
// protocol-specific fields
parameter.Add("type", server.TransferProtocol);
@@ -127,7 +127,7 @@ namespace Netch.Servers.V2ray
if (server.TLSSecureType == "xtls")
{
var flow = ((VLESS.VLESS) server).Flow;
var flow = ((VLESS.VLESS)server).Flow;
if (!flow.IsNullOrWhiteSpace())
parameter.Add("flow", flow!.Replace("-udp443", ""));
}

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Netch.Servers.VMess;
using System.Collections.Generic;
namespace Netch.Servers.VLESS
{

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Netch.Forms;
using System.Collections.Generic;
namespace Netch.Servers.VLESS.VLESSForm
{
@@ -30,8 +30,8 @@ namespace Netch.Servers.VLESS.VLESSForm
CreateTextBox("QUICSecret", "QUIC Secret", s => true, s => server.QUICSecret = s, server.QUICSecret);
CreateComboBox("UseMux",
"Use Mux",
new List<string> {"", "true", "false"},
s => server.UseMux = s switch {"" => null, "true" => true, "false" => false, _ => null},
new List<string> { "", "true", "false" },
s => server.UseMux = s switch { "" => null, "true" => true, "false" => false, _ => null },
server.UseMux?.ToString().ToLower() ?? "");
CreateComboBox("TLSSecure", "TLS Secure", VLESSGlobal.TLSSecure, s => server.TLSSecureType = s, server.TLSSecureType);

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.V2ray;
using System;
using System.Collections.Generic;
namespace Netch.Servers.VLESS
{
@@ -16,13 +16,13 @@ namespace Netch.Servers.VLESS
public string ShortName { get; } = "VL";
public string[] UriScheme { get; } = {"vless"};
public string[] UriScheme { get; } = { "vless" };
public Type ServerType { get; } = typeof(VLESS);
public void Edit(Server s)
{
new VLESSForm.VLESSForm((VLESS) s).ShowDialog();
new VLESSForm.VLESSForm((VLESS)s).ShowDialog();
}
public void Create()

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Netch.Forms;
using Netch.Forms;
using System.Collections.Generic;
namespace Netch.Servers.VMess.Form
{
@@ -25,8 +25,8 @@ namespace Netch.Servers.VMess.Form
CreateTextBox("QUICSecret", "QUIC Secret", s => true, s => server.QUICSecret = s, server.QUICSecret);
CreateComboBox("UseMux",
"Use Mux",
new List<string> {"", "true", "false"},
s => server.UseMux = s switch {"" => null, "true" => true, "false" => false, _ => null},
new List<string> { "", "true", "false" },
s => server.UseMux = s switch { "" => null, "true" => true, "false" => false, _ => null },
server.UseMux?.ToString().ToLower() ?? "");
CreateComboBox("TLSSecure", "TLS Secure", VMessGlobal.TLSSecure, s => server.TLSSecureType = s, server.TLSSecureType);

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Netch.Models;
using System.Collections.Generic;
namespace Netch.Servers.VMess
{

View File

@@ -1,14 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.V2ray;
using Netch.Servers.V2ray.Models;
using Netch.Servers.VMess.Form;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Netch.Servers.VMess
{
@@ -22,13 +22,13 @@ namespace Netch.Servers.VMess
public string ShortName { get; } = "V2";
public string[] UriScheme { get; } = {"vmess"};
public string[] UriScheme { get; } = { "vmess" };
public Type ServerType { get; } = typeof(VMess);
public void Edit(Server s)
{
new VMessForm((VMess) s).ShowDialog();
new VMessForm((VMess)s).ShowDialog();
}
public void Create()
@@ -40,22 +40,22 @@ namespace Netch.Servers.VMess
{
if (Global.Settings.V2RayConfig.V2rayNShareLink)
{
var server = (VMess) s;
var server = (VMess)s;
var vmessJson = JsonSerializer.Serialize(new V2rayNSharing
{
v = 2,
ps = server.Remark,
add = server.Hostname,
port = server.Port,
id = server.UserID,
aid = server.AlterID,
net = server.TransferProtocol,
type = server.FakeType,
host = server.Host,
path = server.Path,
tls = server.TLSSecureType
},
{
v = 2,
ps = server.Remark,
add = server.Hostname,
port = server.Port,
id = server.UserID,
aid = server.AlterID,
net = server.TransferProtocol,
type = server.FakeType,
host = server.Host,
path = server.Path,
tls = server.TLSSecureType
},
new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
@@ -87,7 +87,7 @@ namespace Netch.Servers.VMess
}
V2rayNSharing vmess = JsonSerializer.Deserialize<V2rayNSharing>(s,
new JsonSerializerOptions {NumberHandling = JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString})!;
new JsonSerializerOptions { NumberHandling = JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString })!;
data.Remark = vmess.ps;
data.Hostname = vmess.add;
@@ -114,7 +114,7 @@ namespace Netch.Servers.VMess
data.TLSSecureType = vmess.tls;
data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个
return new[] {data};
return new[] { data };
}
public bool CheckServer(Server s)

View File

@@ -1,3 +1,7 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -6,10 +10,6 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using Netch.Controllers;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Updater
{
@@ -92,7 +92,7 @@ namespace Netch.Updater
#region Apply Update
private static readonly ImmutableArray<string> KeepDirectories = new List<string> {"data", "mode\\Custom", "logging"}.ToImmutableArray();
private static readonly ImmutableArray<string> KeepDirectories = new List<string> { "data", "mode\\Custom", "logging" }.ToImmutableArray();
private void ApplyUpdate()
{

View File

@@ -1,11 +1,11 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Session;
using Netch.Controllers;
using Netch.Models;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Netch.Utils
{
@@ -14,7 +14,7 @@ namespace Netch.Utils
public static ulong received;
public static TraceEventSession? tSession;
private static readonly string[] Suffix = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
private static readonly string[] Suffix = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" };
/// <summary>
/// 计算流量
@@ -98,7 +98,7 @@ namespace Netch.Utils
{
if (processList.Contains(data.ProcessID))
lock (counterLock)
received += (ulong) data.size;
received += (ulong)data.size;
// Debug.WriteLine($"TcpIpRecv: {ToByteSize(data.size)}");
};
@@ -107,7 +107,7 @@ namespace Netch.Utils
{
if (processList.Contains(data.ProcessID))
lock (counterLock)
received += (ulong) data.size;
received += (ulong)data.size;
// Debug.WriteLine($"UdpIpRecv: {ToByteSize(data.size)}");
};

View File

@@ -1,9 +1,9 @@
using System;
using Netch.Models;
using System;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.Models;
namespace Netch.Utils
{

View File

@@ -1,10 +1,10 @@
using System;
using System.IO;
using System.Linq;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5;
using System;
using System.IO;
using System.Linq;
namespace Netch.Utils
{
@@ -113,11 +113,11 @@ namespace Netch.Utils
{
case 0:
return server switch
{
Socks5 => true,
Shadowsocks shadowsocks when !shadowsocks.HasPlugin() && Global.Settings.Redirector.RedirectorSS => true,
_ => false
};
{
Socks5 => true,
Shadowsocks shadowsocks when !shadowsocks.HasPlugin() && Global.Settings.Redirector.RedirectorSS => true,
_ => false
};
case 1:
case 2:
return server is Socks5;
@@ -126,7 +126,7 @@ namespace Netch.Utils
}
}
public static readonly int[] ModeTypes = {0, 1, 2, 6};
public static readonly int[] ModeTypes = { 0, 1, 2, 6 };
public static IModeController GetModeControllerByType(int type, out ushort? port, out string portName)
{

View File

@@ -33,9 +33,9 @@ namespace Netch.Utils
if (port == 0)
throw new ArgumentOutOfRangeException();
var row = GetTcpTable2().Where(r => ntohs((ushort) r.dwLocalPort) == port).Where(r => r.dwOwningPid is not (0 or 4));
var row = GetTcpTable2().Where(r => ntohs((ushort)r.dwLocalPort) == port).Where(r => r.dwOwningPid is not (0 or 4));
return row.Select(r => Process.GetProcessById((int) r.dwOwningPid));
return row.Select(r => Process.GetProcessById((int)r.dwOwningPid));
}
private static void GetReservedPortRange(PortType portType, ref List<Range> targetList)
@@ -143,7 +143,7 @@ namespace Netch.Utils
var random = new Random();
for (ushort i = 0; i < 55535; i++)
{
var p = (ushort) random.Next(10000, 65535);
var p = (ushort)random.Next(10000, 65535);
try
{
CheckPort(p, portType);

View File

@@ -1,7 +1,7 @@
using System;
using Netch.Models;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.Models;
namespace Netch.Utils
{
@@ -16,7 +16,7 @@ namespace Netch.Utils
try
{
var type = ServerHelper.GetTypeByTypeName(jsonElement.GetProperty("Type").GetString()!);
return (Server) JsonSerializer.Deserialize(jsonElement.GetRawText(), type)!;
return (Server)JsonSerializer.Deserialize(jsonElement.GetRawText(), type)!;
}
catch
{

View File

@@ -1,10 +1,10 @@
using Netch.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Timers;
using Netch.Models;
using Range = Netch.Models.Range;
namespace Netch.Utils
@@ -17,7 +17,7 @@ namespace Netch.Utils
.GetExportedTypes()
.Where(type => type.GetInterfaces().Contains(typeof(IServerUtil)));
ServerUtils = serversUtilsTypes.Select(t => (IServerUtil) Activator.CreateInstance(t)!).OrderBy(util => util.Priority);
ServerUtils = serversUtilsTypes.Select(t => (IServerUtil)Activator.CreateInstance(t)!).OrderBy(util => util.Priority);
}
public static Type GetTypeByTypeName(string typeName)
@@ -57,7 +57,7 @@ namespace Netch.Utils
}
}
public static int Interval => (int) (Timer.Interval / 1000);
public static int Interval => (int)(Timer.Interval / 1000);
private static bool ValueIsEnabled(int value)
{
@@ -74,7 +74,7 @@ namespace Netch.Utils
try
{
_mux = true;
Parallel.ForEach(Global.Settings.Server, new ParallelOptions {MaxDegreeOfParallelism = 16}, server => { server.Test(); });
Parallel.ForEach(Global.Settings.Server, new ParallelOptions { MaxDegreeOfParallelism = 16 }, server => { server.Test(); });
_mux = false;
TestDelayFinished?.Invoke(null, new EventArgs());
}

View File

@@ -1,12 +1,12 @@
using System;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Shadowsocks.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Shadowsocks.Models;
namespace Netch.Utils
{
@@ -122,7 +122,7 @@ namespace Netch.Utils
return JsonSerializer.Deserialize<Server>(text,
new JsonSerializerOptions
{
Converters = {new ServerConverterWithTypeDiscriminator()}
Converters = { new ServerConverterWithTypeDiscriminator() }
})!;
}
@@ -158,7 +158,7 @@ namespace Netch.Utils
private static string RemoveEmoji(string text)
{
byte[] emojiBytes = {240, 159};
byte[] emojiBytes = { 240, 159 };
var remark = Encoding.UTF8.GetBytes(text);
var startIndex = 0;
while (remark.Length > startIndex + 1 && remark[startIndex] == emojiBytes[0] && remark[startIndex + 1] == emojiBytes[1])

View File

@@ -48,7 +48,7 @@ namespace Netch.Utils
var sb = new StringBuilder();
foreach (var t in value)
{
var escapeCharacters = new[] {'\\', '*', '+', '?', '|', '{', '}', '[', ']', '(', ')', '^', '$', '.'};
var escapeCharacters = new[] { '\\', '*', '+', '?', '|', '{', '}', '[', ']', '(', ')', '^', '$', '.' };
if (escapeCharacters.Any(s => s == t))
sb.Append('\\');

View File

@@ -1,9 +1,9 @@
using Netch.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Netch.Models;
namespace Netch.Utils
{

View File

@@ -1,3 +1,5 @@
using MaxMind.GeoIP2;
using Microsoft.Win32.TaskScheduler;
using System;
using System.ComponentModel;
using System.Diagnostics;
@@ -11,8 +13,6 @@ using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MaxMind.GeoIP2;
using Microsoft.Win32.TaskScheduler;
using Task = System.Threading.Tasks.Task;
namespace Netch.Utils
@@ -219,8 +219,8 @@ namespace Netch.Utils
{
case TextBox _:
case ComboBox _:
if (((Control) component).ForeColor != color)
((Control) component).ForeColor = color;
if (((Control)component).ForeColor != color)
((Control)component).ForeColor = color;
break;
}

View File

@@ -19,7 +19,7 @@ namespace Netch.Utils
public static HttpWebRequest CreateRequest(string url, int? timeout = null, string? userAgent = null)
{
var req = (HttpWebRequest) WebRequest.Create(url);
var req = (HttpWebRequest)WebRequest.Create(url);
req.UserAgent = string.IsNullOrWhiteSpace(userAgent) ? DefaultUserAgent : userAgent;
req.Accept = "*/*";
req.KeepAlive = true;
@@ -53,7 +53,7 @@ namespace Netch.Utils
/// <returns></returns>
public static string DownloadString(HttpWebRequest req, out HttpWebResponse rep, string encoding = "UTF-8")
{
rep = (HttpWebResponse) req.GetResponse();
rep = (HttpWebResponse)req.GetResponse();
using var responseStream = rep.GetResponseStream();
using var streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encoding));
@@ -83,7 +83,7 @@ namespace Netch.Utils
/// <returns></returns>
public static async Task DownloadFileAsync(HttpWebRequest req, string fileFullPath)
{
using var webResponse = (HttpWebResponse) await req.GetResponseAsync();
using var webResponse = (HttpWebResponse)await req.GetResponseAsync();
await using var input = webResponse.GetResponseStream();
await using var fileStream = File.OpenWrite(fileFullPath);

View File

@@ -1,4 +1,5 @@
using System.Collections;
using Netch.Properties;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -6,7 +7,6 @@ using System.Linq;
using System.Text;
using System.Text.Json;
using System.Windows.Forms;
using Netch.Properties;
namespace Netch.Utils
{
@@ -99,14 +99,14 @@ namespace Netch.Utils
{
for (var i = 0; i < args.Length; i++)
if (args[i] is string)
args[i] = Translate((string) args[i]);
args[i] = Translate((string)args[i]);
return string.Format(Translate(format), args);
}
public static List<string> GetTranslateList()
{
var translateFile = new List<string> {"System", "zh-CN", "en-US"};
var translateFile = new List<string> { "System", "zh-CN", "en-US" };
if (!Directory.Exists("i18n"))
return translateFile;

View File

@@ -47,7 +47,7 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
- XMR *48ju3ELNZEa6wwPBMexCJ9G218BGY2XwhH6B6bmkFuJ3QgM4hPw2Pra35jPtuBZSc7SLNWeBpiWJZWjQeMAiLnTx2tH2Efx*
## Screenshots
![](images/screenshots/main.png)
![](screenshots/main.png)
## Requirements
- [.NET 5](https://dotnet.microsoft.com/download/dotnet/5.0/runtime)

View File

@@ -22,7 +22,11 @@ param (
$PublishSingleFile = $True
)
.\download.ps1 $OutputPath
.\scripts\download.ps1 $OutputPath
if ( -Not $? ) {
Exit 1
}
Write-Host "Building $Configuration to $OutputPath"
dotnet publish `

View File

@@ -1,36 +1,39 @@
param([string]$OutputPath)
$NetchDataURL="https://github.com/NetchX/NetchData/archive/refs/heads/master.zip"
$NetchModeURL="https://github.com/NetchX/NetchMode/archive/refs/heads/master.zip"
$NetchI18NURL="https://github.com/NetchX/NetchTranslation/archive/refs/heads/master.zip"
$last=$(Get-Location)
New-Item -ItemType Directory -Name $OutputPath | Out-Null
Set-Location $OutputPath
Invoke-WebRequest -Uri $NetchDataURL -OutFile data.zip
Invoke-WebRequest -Uri $NetchModeURL -OutFile mode.zip
Invoke-WebRequest -Uri $NetchI18NURL -OutFile i18n.zip
Expand-Archive -Force -Path data.zip -DestinationPath .
Expand-Archive -Force -Path mode.zip -DestinationPath .
Expand-Archive -Force -Path i18n.zip -DestinationPath .
New-Item -ItemType Directory -Name bin | Out-Null
New-Item -ItemType Directory -Name mode | Out-Null
New-Item -ItemType Directory -Name i18n | Out-Null
Copy-Item -Recurse -Force .\NetchData-master\* .\bin
Copy-Item -Recurse -Force .\NetchMode-master\mode\* .\mode
Copy-Item -Recurse -Force .\NetchTranslation-master\i18n\* .\i18n
Remove-Item -Recurse -Force NetchData-master
Remove-Item -Recurse -Force NetchMode-master
Remove-Item -Recurse -Force NetchTranslation-master
Remove-Item -Force data.zip
Remove-Item -Force mode.zip
Remove-Item -Force i18n.zip
Get-Item *
Set-Location $last
exit 0
param([string]$OutputPath)
$NetchDataURL="https://github.com/NetchX/NetchData/archive/refs/heads/master.zip"
$NetchModeURL="https://github.com/NetchX/NetchMode/archive/refs/heads/master.zip"
$NetchI18NURL="https://github.com/NetchX/NetchI18N/archive/refs/heads/master.zip"
$last=$(Get-Location)
New-Item -ItemType Directory -Name $OutputPath | Out-Null
Set-Location $OutputPath
Invoke-WebRequest -Uri $NetchDataURL -OutFile data.zip
Invoke-WebRequest -Uri $NetchModeURL -OutFile mode.zip
Invoke-WebRequest -Uri $NetchI18NURL -OutFile i18n.zip
Expand-Archive -Force -Path data.zip -DestinationPath .
Expand-Archive -Force -Path mode.zip -DestinationPath .
Expand-Archive -Force -Path i18n.zip -DestinationPath .
New-Item -ItemType Directory -Name bin | Out-Null
New-Item -ItemType Directory -Name mode | Out-Null
New-Item -ItemType Directory -Name i18n | Out-Null
Copy-Item -Recurse -Force .\NetchData-master\* .\bin
Copy-Item -Recurse -Force .\NetchMode-master\mode\* .\mode
Copy-Item -Recurse -Force .\NetchI18N-master\i18n\* .\i18n
Remove-Item -Recurse -Force NetchData-master
Remove-Item -Recurse -Force NetchMode-master
Remove-Item -Recurse -Force NetchI18N-master
Remove-Item -Force data.zip
Remove-Item -Force mode.zip
Remove-Item -Force i18n.zip
..\scripts\downloads\cloak.ps1 -OutputPath bin
..\scripts\downloads\xray-core.ps1 -OutputPath bin
Get-Item *
Set-Location $last
exit 0

View File

@@ -0,0 +1,7 @@
param([string]$OutputPath)
$address="https://github.com/cbeuw/Cloak/releases/download/v2.5.3/ck-client-windows-amd64-v2.5.3.exe"
Invoke-WebRequest -Uri $address -OutFile ck-client.exe
Move-Item -Force ck-client.exe $OutputPath
exit 0

View File

@@ -0,0 +1,13 @@
param([string]$OutputPath)
$address="https://github.com/XTLS/Xray-core/releases/download/v1.4.2/Xray-windows-64.zip"
Invoke-WebRequest -Uri $address -OutFile xray-core.zip
Expand-Archive -Force -Path xray-core.zip -DestinationPath xray-core
Move-Item -Force xray-core\xray.exe $OutputPath
Move-Item -Force xray-core\geoip.dat $OutputPath
Move-Item -Force xray-core\geosite.dat $OutputPath
Remove-Item -Recurse -Force xray-core
Remove-Item -Recurse -Force xray-core.zip
exit 0