Compare commits

..

70 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
Connection Refused
1099b2c6e6 Bump version to 1.8.3-Beta114514 2021-04-02 02:20:36 +08:00
Connection Refused
295c5958fd Update release.yml 2021-04-02 02:14:34 +08:00
Connection Refused
9a3a85078e Update release.yml 2021-04-02 02:13:03 +08:00
Connection Refused
c14fa70a08 Update download.ps1 2021-04-02 02:04:23 +08:00
Connection Refused
ebcde8cf55 Update build.ps1 2021-04-02 02:00:28 +08:00
Connection Refused
5fca9c55fe Update build.yml 2021-04-02 01:59:23 +08:00
Connection Refused
9f105425ab Update 2021-04-02 01:59:19 +08:00
Connection Refused
4a3d6c49d0 Add files via upload 2021-04-02 01:51:59 +08:00
Connection Refused
fa23561827 Update build.yml 2021-04-02 01:49:24 +08:00
Connection Refused
96b8c42918 Update build.yml 2021-04-02 01:44:27 +08:00
Connection Refused
9b41ea99e5 Update build.yml 2021-04-02 01:43:19 +08:00
Connection Refused
6099891280 Update build.yml 2021-04-02 01:38:33 +08:00
Connection Refused
b8676df2ab Update build.yml 2021-04-02 01:36:17 +08:00
Connection Refused
5970e30974 m 2021-04-02 01:34:56 +08:00
ChsBuffer
37455bb89e Update nfapinet interop 2021-04-02 00:19:57 +08:00
ChsBuffer
9437ec7e5d Update CI(Pull Binaries LFS) 2021-04-01 23:49:53 +08:00
ChsBuffer
93faf8a82e Update submodules 2021-04-01 23:49:25 +08:00
Connection Refused
8a5c0dcd1d Update ci.yml 2021-04-01 23:13:27 +08:00
Connection Refused
559f1dc8a9 Update Redirector 2021-04-01 21:30:32 +08:00
Bruce Wayne
d0c71698aa Update issue forms 2021-04-01 20:24:58 +08:00
Bruce Wayne
98bf6c3c9b Update feature_request.yml 2021-04-01 20:19:37 +08:00
Bruce Wayne
8a6970cc26 Update bug_report.yml 2021-04-01 20:00:39 +08:00
Bruce Wayne
c0b1ae193b Update bug_report.zh-CN.yml 2021-04-01 19:41:45 +08:00
Bruce Wayne
f7d8af6592 New issue forms 2021-04-01 19:35:33 +08:00
Connection Refused
7d7643ad77 Update submodules 2021-04-01 04:36:00 +08:00
Connection Refused
15f9c6d4f5 Update README.zh-CN.md 2021-04-01 04:17:51 +08:00
Connection Refused
732066ccf8 Update README.md 2021-04-01 04:17:37 +08:00
ChsBuffer
483dccc5d2 trim 2021-03-31 19:56:28 +08:00
ChsBuffer
42b609b597 Refactor OpenLogFile 2021-03-31 19:56:23 +08:00
ChsBuffer
7ab89b67c5 Update BUILD.ps1 2021-03-31 18:45:21 +08:00
ChsBuffer
a33c2c3757 Fix Utils.SHA256CheckSum file handle not closed 2021-03-31 17:29:26 +08:00
AmazingDM
268bdb7730 Update UpdateChecker.cs 2021-03-30 14:14:19 +08:00
Connection Refused
ed459ec8d6 Update submodules 2021-03-29 23:39:23 +08:00
Connection Refused
ddd1ca5fac Update NFController 2021-03-29 23:34:20 +08:00
Connection Refused
7c54c1f570 Update Redirector 2021-03-29 23:32:12 +08:00
AmazingDM
ed56d51c4d Update binaries(ICMP hijack) 2021-03-28 22:11:54 +08:00
ChsBuffer
c669097aa5 Update csproj 2021-03-28 16:26:11 +08:00
ChsBuffer
5d74321771 Update MarkFilesOld 2021-03-28 03:52:25 +08:00
ChsBuffer
093fe6404b Updater Skip mark logging directory 2021-03-28 03:49:51 +08:00
ChsBuffer
2760b3c7bd Update TUNController 2021-03-28 03:40:24 +08:00
ChsBuffer
ba17366094 trim 2021-03-28 03:32:21 +08:00
ChsBuffer
6c668684e9 Remove AdapterUtil 2021-03-28 03:29:24 +08:00
ChsBuffer
8d6e4bdd96 Fix Publish Build Missing NTT.exe 2021-03-28 03:15:31 +08:00
120 changed files with 1130 additions and 2407 deletions

1
.gitattributes vendored Normal file
View File

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

55
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: Bug report
description: "Create a report to help us improve"
title: ""
labels: 需要核实
issue_body: true
body:
- type: markdown
attributes:
value: "**Make sure you have read the readme, searched and read the issues related to yours. Otherwise it will be considered as a duplicate which will be closed immediately.**"
- type: textarea
id: error
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: To Reproduce
placeholder: |
Steps to reproduce the behavior:
1. Open Netch
2. ...
validations:
required: true
- type: checkboxes
id: captcha
attributes:
label: CAPTCHA
description: Please confirm the options below.
options:
- label: I am human
required: true
- type: textarea
id: log
attributes:
render: shell
label: Log
description: Attaching any log files in the folder `Netch\logging` is strongly recommended.
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment
placeholder: |
- OS: [e.g. Windows 10 Pro 64-bit 1903]
- Netch Version: [e.g. 1.0.0-STABLE.x64]
validations:
required: true
- type: markdown
attributes:
value: |
In the text box below, you can attach any relevant screenshots and files.

View File

@@ -0,0 +1,54 @@
name: 错误报告
description: "创建错误报告以帮助我们改进"
title: ""
labels: 需要核实
issue_body: true
body:
- type: markdown
attributes:
value: "**确保你已经看过 readme也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**"
- type: textarea
id: error
attributes:
label: "错误描述"
description: 对错误的清晰简洁描述
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: "复现步骤"
placeholder: |
1. 打开 Netch 软件
2. ...
validations:
required: true
- type: checkboxes
id: captcha
attributes:
label: 验证
description: 请确认下面选项
options:
- label: 我是人类
required: true
- type: textarea
id: log
attributes:
render: shell
label: 日志
description: 强烈建议附上任何在 `Netch\logging` 文件夹下面的日志
validations:
required: true
- type: textarea
id: environment
attributes:
label: 操作环境
placeholder: |
操作系统:[Windows 10 专业版 64 位 1903]
软件版本:[1.0.0-STABLE 64 位]
validations:
required: true
- type: markdown
attributes:
value: |
下面的文本框中你可以附上跟 issue 相关的截图、文件

View File

@@ -0,0 +1,16 @@
name: request
description: "Suggest an idea for this project"
title: ""
labels: 需要核实
issue_body: true
body:
- type: markdown
attributes:
value: "**Make sure you have read the readme, searched and read the issues related to yours. Otherwise it will be considered as a duplicate which will be closed immediately.**"
- type: textarea
id: description
attributes:
label: "Describe the feature you want"
description: A clear and concise description of what you want to happen.
validations:
required: true

View File

@@ -0,0 +1,16 @@
name: 功能请求
description: "建议这个项目的想法"
title: ""
labels: 需要核实
issue_body: true
body:
- type: markdown
attributes:
value: "**确保你已经看过 readme也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**"
- type: textarea
id: description
attributes:
label: "功能描述"
description: 简明扼要地描述需要的功能
validations:
required: true

27
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Netch Build CI
on: [push, pull_request]
jobs:
build:
name: Build
runs-on: windows-latest
steps:
- name: MSBuild
uses: microsoft/setup-msbuild@v1.0.2
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Build
shell: pwsh
run: |
.\build.ps1 -Configuration Release -OutputPath release
- name: Upload
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: actions/upload-artifact@v2
with:
name: Netch
path: release

View File

@@ -1,30 +0,0 @@
name: Netch CI
on:
push:
branches-ignore:
dependabot/**
pull_request:
jobs:
build:
name: Build
runs-on: windows-latest
steps:
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1.0.2
- name: Checkout
uses: actions/checkout@v2
with:
submodules: true
- name: Build Solution
shell: pwsh
run: .\BUILD.ps1
- name: Upload Artifact
continue-on-error: true
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: actions/upload-artifact@v2
with:
name: Netch
path: Netch\bin\x64\Release

View File

@@ -1,44 +1,44 @@
name: Netch Release name: Netch Release CI
on: on:
push: push:
tags: tags:
- '*.*' - '*.*.*'
jobs: jobs:
build: build:
name: Build name: Build
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Setup MSBuild - name: MSBuild
uses: microsoft/setup-msbuild@v1.0.2 uses: microsoft/setup-msbuild@v1.0.2
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
submodules: true fetch-depth: 1
- name: Build Solution - name: Build
shell: pwsh
run: .\PUBLISH.ps1
- name: Package
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
shell: pwsh shell: pwsh
run: | run: |
New-Item -ItemType Directory -Path C:\builtfiles -Force > $null .\build.ps1 -Configuration Release -OutputPath release
7z a -mx9 C:\builtfiles\Netch.7z .\Netch\bin\Publish\
7z rn C:\builtfiles\Netch.7z Publish Netch - name: Package
echo "Netch_SHA256=$(.\GetSHA256.ps1 C:\builtfiles\Netch.7z)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append shell: pwsh
echo "Netch_EXE_SHA256=$(.\GetSHA256.ps1 Netch\bin\Publish\Netch.exe)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append run: |
7z a -mx9 Netch.7z release
7z rn Netch.7z release Netch
echo "NETCH_SHA256=$(.\sha256.ps1 Netch.7z)" | Out-File -Append -Encoding UTF8 -FilePath $Env:GITHUB_ENV
- name: Release - name: Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
env: env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
prerelease: ${{ contains(github.ref, '-') }} prerelease: ${{ contains(github.ref, '-') }}
draft: false draft: false
files: | files: |
C:\builtfiles\Netch.7z Netch.7z
body: | body: |
[![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/Netch) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/Netch_Discuss_Group) [![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/Netch) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/Netch_Discuss_Group)

10
.gitignore vendored
View File

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

9
.gitmodules vendored
View File

@@ -1,9 +0,0 @@
[submodule "binaries"]
path = binaries
url = https://github.com/NetchX/NetchBinaries
[submodule "modes"]
path = modes
url = https://github.com/NetchX/NetchMode
[submodule "translations"]
path = translations
url = https://github.com/NetchX/NetchTranslation

View File

@@ -1,11 +0,0 @@
Write-Host 'Building'
dotnet build -p:Configuration="Release" `
-p:Platform="x64" `
-p:SolutionDir="$pwd\" `
-restore `
Netch\Netch.csproj
if ($LASTEXITCODE) { exit $LASTEXITCODE }
Write-Host 'Build done'

53
GSF.md
View File

@@ -1,53 +0,0 @@
```json
{
"Type": "",
"Rate": 1,
"Remark": "",
"Hostname": "",
"Port": 0,
"Username": "",
"Password": "",
"EncryptMethod": "",
"Plugin": "",
"PluginOption": "",
"Protocol": "",
"ProtocolParam": "",
"OBFS": "",
"OBFSParam": "",
"UserID": "",
"AlterID": 0,
"TransferProtocol": "",
"FakeType": "",
"Host": "",
"Path": "",
"QUICSecure": "",
"QUICSecret": "",
"TLSSecure": false
}
```
| 字段 | 说明 |
| :- | :- |
| Type | 代理类型HTTP、HTTPS、Socks5、SS、SSR、VMess |
| Rate | 倍率 |
| Remark | 备注 |
| Hostname | 主机名 |
| Port | 端口 |
| Username | 账号HTTP、HTTPS、Socks5 |
| Password | 密码HTTP、HTTPS、Socks5、SS、SSR |
| UserID | 用户 IDVMess |
| AlterID | 额外 IDVMess |
| EncryptMethod | 加密方式SS、SSR、VMess |
| Plugin | 插件SS |
| PluginOption | 插件参数SS |
| Protocol | 协议SSR |
| ProtocolParam | 协议参数SSR |
| OBFS | 混淆SSR |
| OBFSParam | 混淆参数SSR |
| TransferProtcol | 传输协议VMess |
| FakeType | 伪装类型VMess |
| Host | 伪装域名VMess |
| Path | 传输路径VMess |
| QUICSecure | QUIC 加密方式VMess |
| QUICSecret | QUIC 加密密钥VMess |
| TLSSecure | TLS 底层传输安全VMess |

View File

@@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows7</TargetFramework>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>none</DebugType>
</PropertyGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -1,36 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5 VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "UnitTest\UnitTest.csproj", "{53397641-35CA-4336-8E22-2CE12EF476AC}" Global
EndProject GlobalSection(SolutionConfigurationPlatforms) = preSolution
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.nfapinet", "Interop.nfapinet\Interop.nfapinet.csproj", "{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}" Debug|x64 = Debug|x64
EndProject Release|x64 = Release|x64
Global EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
Debug|x64 = Debug|x64 {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.ActiveCfg = Debug|x64
Release|x64 = Release|x64 {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.Build.0 = Debug|x64
EndGlobalSection {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.ActiveCfg = Release|x64
GlobalSection(ProjectConfigurationPlatforms) = postSolution {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.ActiveCfg = Debug|x64 EndGlobalSection
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.Build.0 = Debug|x64 GlobalSection(SolutionProperties) = preSolution
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.ActiveCfg = Release|x64 HideSolutionNode = FALSE
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64 EndGlobalSection
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.ActiveCfg = Debug|x64 GlobalSection(ExtensibilityGlobals) = postSolution
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.Build.0 = Debug|x64 SolutionGuid = {6EC9B043-ACA5-4BB9-96DB-493A2EF6E43F}
{53397641-35CA-4336-8E22-2CE12EF476AC}.Release|x64.ActiveCfg = Release|x64 EndGlobalSection
{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}.Debug|x64.ActiveCfg = Debug|Any CPU EndGlobal
{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}.Debug|x64.Build.0 = Debug|Any CPU
{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}.Release|x64.ActiveCfg = Release|Any CPU
{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}.Release|x64.Build.0 = Release|Any CPU
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;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@@ -7,15 +9,13 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Netch.Models;
using Netch.Utils;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
namespace Netch.Controllers namespace Netch.Controllers
{ {
public abstract class Guard public abstract class Guard
{ {
private readonly Timer _flushFileStreamTimer = new(300) {AutoReset = true}; private readonly Timer _flushFileStreamTimer = new(300) { AutoReset = true };
private FileStream? _logFileStream; private FileStream? _logFileStream;
@@ -84,7 +84,7 @@ namespace Netch.Controllers
} }
catch (Win32Exception e) catch (Win32Exception e)
{ {
Logging.Error($"停止 {MainFile} 错误:\n" + e); Global.Logger.Error($"停止 {MainFile} 错误:\n" + e);
} }
catch catch
{ {
@@ -268,7 +268,7 @@ namespace Netch.Controllers
} }
catch (Exception exception) catch (Exception exception)
{ {
Logging.Warning($"写入 {Name} 日志错误:\n" + exception.Message); Global.Logger.Warning($"写入 {Name} 日志错误:\n" + exception.Message);
} }
} }
} }

View File

@@ -1,9 +1,9 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Netch.Models; using Netch.Models;
using Netch.Servers.Socks5; using Netch.Servers.Socks5;
using Netch.Utils; using Netch.Utils;
using System;
using System.IO;
using System.Threading.Tasks;
namespace Netch.Controllers namespace Netch.Controllers
{ {
@@ -54,17 +54,17 @@ namespace Netch.Controllers
public static void Start(Server server, Mode mode) public static void Start(Server server, Mode mode)
{ {
Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}"); Global.Logger.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}");
Server = server; Server = server;
Mode = mode; Mode = mode;
// 刷新DNS缓存 // 刷新 DNS 缓存
NativeMethods.FlushDNSResolverCache(); NativeMethods.RefreshDNSCache();
if (DnsUtils.Lookup(server.Hostname) == null) if (DnsUtils.Lookup(server.Hostname) == null)
throw new MessageException(i18N.Translate("Lookup Server hostname failed")); throw new MessageException(i18N.Translate("Lookup Server hostname failed"));
// 添加Netch到防火墙 // 添加 Netch 到防火墙
Firewall.AddNetchFwRules(); Firewall.AddNetchFwRules();
try try
@@ -89,8 +89,8 @@ namespace Netch.Controllers
case MessageException: case MessageException:
throw; throw;
default: default:
Logging.Error(e.ToString()); Global.Logger.Error(e.ToString());
Utils.Utils.Open(Logging.LogFile); Global.Logger.ShowLog();
throw new MessageException($"未处理异常\n{e.Message}"); throw new MessageException($"未处理异常\n{e.Message}");
} }
} }
@@ -122,7 +122,7 @@ namespace Netch.Controllers
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName); ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName);
if (port != null) if (port != null)
TryReleaseTcpPort((ushort) port, portName); TryReleaseTcpPort((ushort)port, portName);
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name)); Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
@@ -158,8 +158,8 @@ namespace Netch.Controllers
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Error(e.ToString()); Global.Logger.Error(e.ToString());
Utils.Utils.Open(Logging.LogFile); Global.Logger.ShowLog();
} }
ModeController = null; ModeController = null;
@@ -193,7 +193,7 @@ namespace Netch.Controllers
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Warning(e.ToString()); Global.Logger.Warning(e.ToString());
continue; continue;
} }

View File

@@ -1,13 +1,13 @@
using System; using Netch.Interops;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using Netch.Models; using Netch.Models;
using Netch.Servers.Shadowsocks; using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5; using Netch.Servers.Socks5;
using Netch.Utils; using Netch.Utils;
using nfapinet; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using static Netch.Interops.RedirectorInterop; using static Netch.Interops.RedirectorInterop;
namespace Netch.Controllers namespace Netch.Controllers
@@ -25,14 +25,15 @@ namespace Netch.Controllers
{ {
CheckDriver(); CheckDriver();
Dial(NameList.TYPE_FILTLOP, "false"); Dial(NameList.TYPE_FILTERLOOPBACK, "false");
Dial(NameList.TYPE_FILTERICMP, "true");
var p = PortHelper.GetAvailablePort(); var p = PortHelper.GetAvailablePort();
Dial(NameList.TYPE_TCPLISN, p.ToString()); Dial(NameList.TYPE_TCPLISN, p.ToString());
Dial(NameList.TYPE_UDPLISN, p.ToString()); Dial(NameList.TYPE_UDPLISN, p.ToString());
// Server // Server
Dial(NameList.TYPE_FILTUDP, (Global.Settings.Redirector.ProxyProtocol != PortType.TCP).ToString().ToLower()); Dial(NameList.TYPE_FILTERUDP, (Global.Settings.Redirector.ProxyProtocol != PortType.TCP).ToString().ToLower());
Dial(NameList.TYPE_FILTTCP, (Global.Settings.Redirector.ProxyProtocol != PortType.UDP).ToString().ToLower()); Dial(NameList.TYPE_FILTERTCP, (Global.Settings.Redirector.ProxyProtocol != PortType.UDP).ToString().ToLower());
dial_Server(Global.Settings.Redirector.ProxyProtocol); dial_Server(Global.Settings.Redirector.ProxyProtocol);
// Mode Rule // Mode Rule
@@ -175,8 +176,8 @@ namespace Netch.Controllers
var binFileVersion = Utils.Utils.GetFileVersion(BinDriver); var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver); var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
Logging.Info("内置驱动版本: " + binFileVersion); Global.Logger.Info("内置驱动版本: " + binFileVersion);
Logging.Info("系统驱动版本: " + systemFileVersion); Global.Logger.Info("系统驱动版本: " + systemFileVersion);
if (!File.Exists(SystemDriver)) if (!File.Exists(SystemDriver))
{ {
@@ -206,7 +207,7 @@ namespace Netch.Controllers
if (!reinstall) if (!reinstall)
return; return;
Logging.Info("更新驱动"); Global.Logger.Info("更新驱动");
UninstallDriver(); UninstallDriver();
InstallDriver(); InstallDriver();
} }
@@ -217,7 +218,7 @@ namespace Netch.Controllers
/// <returns>驱动是否安装成功</returns> /// <returns>驱动是否安装成功</returns>
private static void InstallDriver() private static void InstallDriver()
{ {
Logging.Info("安装 NF 驱动"); Global.Logger.Info("安装 NF 驱动");
if (!File.Exists(BinDriver)) if (!File.Exists(BinDriver))
throw new MessageException(i18N.Translate("builtin driver files missing, can't install NF driver")); throw new MessageException(i18N.Translate("builtin driver files missing, can't install NF driver"));
@@ -228,7 +229,7 @@ namespace Netch.Controllers
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Error("驱动复制失败\n" + e); Global.Logger.Error("驱动复制失败\n" + e);
throw new MessageException($"Copy NF driver file failed\n{e.Message}"); throw new MessageException($"Copy NF driver file failed\n{e.Message}");
} }
@@ -237,11 +238,11 @@ namespace Netch.Controllers
var result = NFAPI.nf_registerDriver("netfilter2"); var result = NFAPI.nf_registerDriver("netfilter2");
if (result == NF_STATUS.NF_STATUS_SUCCESS) if (result == NF_STATUS.NF_STATUS_SUCCESS)
{ {
Logging.Info("驱动安装成功"); Global.Logger.Info("驱动安装成功");
} }
else else
{ {
Logging.Error($"注册驱动失败,返回值:{result}"); Global.Logger.Error($"注册驱动失败,返回值:{result}");
throw new MessageException($"Register NF driver failed\n{result}"); throw new MessageException($"Register NF driver failed\n{result}");
} }
} }
@@ -252,7 +253,7 @@ namespace Netch.Controllers
/// <returns>是否成功卸载</returns> /// <returns>是否成功卸载</returns>
public static bool UninstallDriver() public static bool UninstallDriver()
{ {
Logging.Info("卸载 NF 驱动"); Global.Logger.Info("卸载 NF 驱动");
try try
{ {
if (NFService.Status == ServiceControllerStatus.Running) if (NFService.Status == ServiceControllerStatus.Running)

View File

@@ -1,8 +1,8 @@
using System; using Netch.Utils;
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Netch.Utils;
namespace Netch.Controllers namespace Netch.Controllers
{ {
@@ -39,7 +39,7 @@ namespace Netch.Controllers
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Warning($"写入 {Name} 日志错误:\n" + e.Message); Global.Logger.Warning($"写入 {Name} 日志错误:\n" + e.Message);
} }
if (output.IsNullOrWhiteSpace()) if (output.IsNullOrWhiteSpace())
@@ -86,7 +86,7 @@ namespace Netch.Controllers
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Error($"{Name} 控制器出错:\n" + e); Global.Logger.Error($"{Name} 控制器出错:\n" + e);
try try
{ {
Stop(); Stop();

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

View File

@@ -1,13 +1,13 @@
using System; using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading.Tasks; using System.Threading.Tasks;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using static Netch.Interops.TUNInterop; using static Netch.Interops.TUNInterop;
namespace Netch.Controllers namespace Netch.Controllers
@@ -84,14 +84,14 @@ namespace Netch.Controllers
#endregion #endregion
Logging.Debug("tun2socks init"); Global.Logger.Debug("tun2socks init");
Init(); Init();
_tunAdapter = new TunAdapter(); _tunAdapter = new TunAdapter();
NativeMethods.CreateUnicastIP((int) AddressFamily.InterNetwork, NativeMethods.CreateUnicastIP(AddressFamily.InterNetwork,
Global.Settings.TUNTAP.Address, Global.Settings.TUNTAP.Address,
Utils.Utils.SubnetToCidr(Global.Settings.TUNTAP.Netmask), (byte)Utils.Utils.SubnetToCidr(Global.Settings.TUNTAP.Netmask),
_tunAdapter.InterfaceIndex); _tunAdapter.InterfaceIndex);
SetupRouteTable(mode); SetupRouteTable(mode);
@@ -104,8 +104,8 @@ namespace Netch.Controllers
{ {
var binHash = Utils.Utils.SHA256CheckSum(BinDriver); var binHash = Utils.Utils.SHA256CheckSum(BinDriver);
var sysHash = Utils.Utils.SHA256CheckSum(SysDriver); var sysHash = Utils.Utils.SHA256CheckSum(SysDriver);
Logging.Info(binHash); Global.Logger.Info("自带 wintun.dll Hash: " + binHash);
Logging.Info(sysHash); Global.Logger.Info("系统 wintun.dll Hash: " + sysHash);
if (binHash == sysHash) if (binHash == sysHash)
return; return;
@@ -115,7 +115,7 @@ namespace Netch.Controllers
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Error(e.ToString()); Global.Logger.Error(e.ToString());
throw new MessageException($"Failed to copy wintun.dll to system directory: {e.Message}"); throw new MessageException($"Failed to copy wintun.dll to system directory: {e.Message}");
} }
} }
@@ -142,13 +142,13 @@ namespace Netch.Controllers
private void SetupRouteTable(Mode mode) private void SetupRouteTable(Mode mode)
{ {
Global.MainForm.StatusText(i18N.Translate("SetupBypass")); Global.MainForm.StatusText(i18N.Translate("SetupBypass"));
Logging.Info("设置路由规则"); Global.Logger.Info("设置路由规则");
Logging.Info("绕行 → 服务器 IP"); Global.Logger.Info("绕行 → 服务器 IP");
if (!IPAddress.IsLoopback(_serverAddresses)) if (!IPAddress.IsLoopback(_serverAddresses))
RouteAction(Action.Create, $"{_serverAddresses}/32", RouteType.Outbound); RouteAction(Action.Create, $"{_serverAddresses}/32", RouteType.Outbound);
Logging.Info("绕行 → 全局绕过 IP"); Global.Logger.Info("绕行 → 全局绕过 IP");
RouteAction(Action.Create, Global.Settings.TUNTAP.BypassIPs, RouteType.Outbound); RouteAction(Action.Create, Global.Settings.TUNTAP.BypassIPs, RouteType.Outbound);
#region Rule IPs #region Rule IPs
@@ -157,12 +157,12 @@ namespace Netch.Controllers
{ {
case 1: case 1:
// 代理规则 IP // 代理规则 IP
Logging.Info("代理 → 规则 IP"); Global.Logger.Info("代理 → 规则 IP");
RouteAction(Action.Create, mode.FullRule, RouteType.TUNTAP); RouteAction(Action.Create, mode.FullRule, RouteType.TUNTAP);
if (Global.Settings.TUNTAP.ProxyDNS) if (Global.Settings.TUNTAP.ProxyDNS)
{ {
Logging.Info("代理 → 自定义 DNS"); Global.Logger.Info("代理 → 自定义 DNS");
if (Global.Settings.TUNTAP.UseCustomDNS) if (Global.Settings.TUNTAP.UseCustomDNS)
RouteAction(Action.Create, Global.Settings.TUNTAP.HijackDNS.Select(ip => $"{ip}/32"), RouteType.TUNTAP); RouteAction(Action.Create, Global.Settings.TUNTAP.HijackDNS.Select(ip => $"{ip}/32"), RouteType.TUNTAP);
else else
@@ -173,7 +173,7 @@ namespace Netch.Controllers
case 2: case 2:
// 绕过规则 IP // 绕过规则 IP
Logging.Info("绕行 → 规则 IP"); Global.Logger.Info("绕行 → 规则 IP");
RouteAction(Action.Create, mode.FullRule, RouteType.Outbound); RouteAction(Action.Create, mode.FullRule, RouteType.Outbound);
break; break;
} }
@@ -182,7 +182,7 @@ namespace Netch.Controllers
if (mode.Type == 2) if (mode.Type == 2)
{ {
Logging.Info("代理 → 全局"); Global.Logger.Info("代理 → 全局");
SetInterface(RouteType.TUNTAP, 0); SetInterface(RouteType.TUNTAP, 0);
RouteAction(Action.Create, "0.0.0.0/0", RouteType.TUNTAP, record: false); RouteAction(Action.Create, "0.0.0.0/0", RouteType.TUNTAP, record: false);
} }
@@ -233,18 +233,18 @@ namespace Netch.Controllers
return false; return false;
IAdapter adapter = routeType switch IAdapter adapter = routeType switch
{ {
RouteType.Outbound => _outboundAdapter, RouteType.Outbound => _outboundAdapter,
RouteType.TUNTAP => _tunAdapter, RouteType.TUNTAP => _tunAdapter,
_ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null) _ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null)
}; };
List<string> ipList = routeType switch List<string> ipList = routeType switch
{ {
RouteType.Outbound => _directIPs, RouteType.Outbound => _directIPs,
RouteType.TUNTAP => _proxyIPs, RouteType.TUNTAP => _proxyIPs,
_ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null) _ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null)
}; };
string gateway = adapter.Gateway.ToString(); string gateway = adapter.Gateway.ToString();
var index = adapter.InterfaceIndex; var index = adapter.InterfaceIndex;
@@ -255,23 +255,21 @@ namespace Netch.Controllers
switch (action) switch (action)
{ {
case Action.Create: 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) if (result && record)
ipList.Add(ipNetwork); ipList.Add(ipNetwork);
break; break;
case Action.Delete: 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; break;
default: default:
throw new ArgumentOutOfRangeException(nameof(action), action, null); throw new ArgumentOutOfRangeException(nameof(action), action, null);
} }
Logging.Debug($"{action}Route(\"{ip}\", {cidr}, \"{gateway}\", {index}, {metric})"); Global.Logger.Debug($"{action}Route(\"{ip}\", {cidr}, \"{gateway}\", {index}, {metric})");
if (!result) if (!result)
{ Global.Logger.Warning($"Failed to invoke {action}Route(\"{ip}\", {cidr}, \"{gateway}\", {index}, {metric})");
Logging.Warning($"Failed to invoke {action}Route(\"{ip}\", {cidr}, \"{gateway}\", {index}, {metric})");
}
return result; return result;
} }
@@ -284,7 +282,7 @@ namespace Netch.Controllers
var s = ipNetwork.Split('/'); var s = ipNetwork.Split('/');
if (s.Length != 2) if (s.Length != 2)
{ {
Logging.Warning($"Failed to parse rule {ipNetwork}"); Global.Logger.Warning($"Failed to parse rule {ipNetwork}");
return false; return false;
} }

View File

@@ -1,4 +1,6 @@
using System; using Netch.Models.GitHubRelease;
using Netch.Utils;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@@ -6,8 +8,6 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Netch.Models.GitHubRelease;
using Netch.Utils;
namespace Netch.Controllers namespace Netch.Controllers
{ {
@@ -20,7 +20,7 @@ namespace Netch.Controllers
public const string Copyright = @"Copyright © 2019 - 2021"; public const string Copyright = @"Copyright © 2019 - 2021";
public const string AssemblyVersion = @"1.8.3"; public const string AssemblyVersion = @"1.8.3";
private const string Suffix = @"Beta5"; private const string Suffix = @"";
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}"; public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
@@ -46,25 +46,25 @@ namespace Netch.Controllers
var json = await WebUtil.DownloadStringAsync(WebUtil.CreateRequest(url)); var json = await WebUtil.DownloadStringAsync(WebUtil.CreateRequest(url));
var releases = JsonSerializer.Deserialize<List<Release>>(json)!; var releases = JsonSerializer.Deserialize<List<Release>>(json)!;
LatestRelease = VersionUtil.GetLatestRelease(releases, isPreRelease); LatestRelease = GetLatestRelease(releases, isPreRelease);
Logging.Info($"Github 最新发布版本: {LatestRelease.tag_name}"); Global.Logger.Info($"Github 最新发布版本: {LatestRelease.tag_name}");
if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0) if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0)
{ {
Logging.Info("发现新版本"); Global.Logger.Info("发现新版本");
NewVersionFound?.Invoke(null, new EventArgs()); NewVersionFound?.Invoke(null, new EventArgs());
} }
else else
{ {
Logging.Info("目前是最新版本"); Global.Logger.Info("目前是最新版本");
NewVersionNotFound?.Invoke(null, new EventArgs()); NewVersionNotFound?.Invoke(null, new EventArgs());
} }
} }
catch (Exception e) catch (Exception e)
{ {
if (e is WebException) if (e is WebException)
Logging.Warning($"获取新版本失败: {e.Message}"); Global.Logger.Warning($"获取新版本失败: {e.Message}");
else else
Logging.Warning(e.ToString()); Global.Logger.Warning(e.ToString());
NewVersionFoundFailed?.Invoke(null, new EventArgs()); NewVersionFoundFailed?.Invoke(null, new EventArgs());
} }
@@ -104,5 +104,14 @@ namespace Netch.Controllers
return sb.ToString(); 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.Diagnostics;
using System.Windows.Forms; using System.Windows.Forms;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms namespace Netch.Forms
{ {
@@ -21,17 +21,17 @@ namespace Netch.Forms
private void NetchPictureBox_Click(object sender, EventArgs e) 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) 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) 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.Linq;
using System.Net; using System.Net;
using System.Windows.Forms; using System.Windows.Forms;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms namespace Netch.Forms
{ {
@@ -54,7 +54,7 @@ namespace Netch.Forms
{ {
Global.Settings.TUNTAP.BypassIPs.Clear(); Global.Settings.TUNTAP.BypassIPs.Clear();
foreach (var ip in IPListBox.Items) foreach (var ip in IPListBox.Items)
Global.Settings.TUNTAP.BypassIPs.Add((string) ip); Global.Settings.TUNTAP.BypassIPs.Add((string)ip);
Configuration.Save(); Configuration.Save();
MessageBoxX.Show(i18N.Translate("Saved")); 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@@ -8,12 +14,6 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; 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 namespace Netch.Forms
{ {
@@ -41,7 +41,7 @@ namespace Netch.Forms
#region i18N Translations #region i18N Translations
_mainFormText.Add(UninstallServiceToolStripMenuItem.Name, new[] {"Uninstall {0}", "NF Service"}); _mainFormText.Add(UninstallServiceToolStripMenuItem.Name, new[] { "Uninstall {0}", "NF Service" });
#endregion #endregion
@@ -63,7 +63,7 @@ namespace Netch.Forms
Text = i18N.TranslateFormat("Add [{0}] Server", fullName) 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; control.Click += AddServerToolStripMenuItem_Click;
ServerToolStripMenuItem.DropDownItems.Add(control); ServerToolStripMenuItem.DropDownItems.Add(control);
} }
@@ -184,7 +184,7 @@ namespace Netch.Forms
return string.Empty; return string.Empty;
if (value is object[] values) 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); return i18N.Translate(value);
} }
@@ -228,7 +228,7 @@ namespace Netch.Forms
throw new ArgumentNullException(nameof(sender)); throw new ArgumentNullException(nameof(sender));
// TODO get Util from Tag // TODO get Util from Tag
var s = ((ToolStripMenuItem) sender).Text; var s = ((ToolStripMenuItem)sender).Text;
var start = s.IndexOf("[", StringComparison.Ordinal) + 1; var start = s.IndexOf("[", StringComparison.Ordinal) + 1;
var end = s.IndexOf("]", start, StringComparison.Ordinal); var end = s.IndexOf("]", start, StringComparison.Ordinal);
@@ -297,7 +297,7 @@ namespace Netch.Forms
catch (Exception e) catch (Exception e)
{ {
NotifyTip(i18N.Translate("update servers failed") + "\n" + e.Message, info: false); NotifyTip(i18N.Translate("update servers failed") + "\n" + e.Message, info: false);
Logging.Error("更新服务器 失败!" + e); Global.Logger.Error("更新服务器 失败!" + e);
} }
finally finally
{ {
@@ -348,7 +348,7 @@ namespace Netch.Forms
{ {
await Task.Run(() => await Task.Run(() =>
{ {
NativeMethods.FlushDNSResolverCache(); NativeMethods.RefreshDNSCache();
DnsUtils.ClearCache(); DnsUtils.ClearCache();
}); });
@@ -432,8 +432,8 @@ namespace Netch.Forms
{ {
if (exception is not MessageException) if (exception is not MessageException)
{ {
Logging.Error($"更新失败: {exception}"); Global.Logger.Error($"更新失败: {exception}");
Utils.Utils.Open(Logging.LogFile); Global.Logger.ShowLog();
} }
NotifyTip(exception.Message, info: false); NotifyTip(exception.Message, info: false);
@@ -704,7 +704,7 @@ namespace Netch.Forms
{ {
try try
{ {
Global.Settings.ModeComboBoxSelectedIndex = Global.Modes.IndexOf((Models.Mode) ModeComboBox.SelectedItem); Global.Settings.ModeComboBoxSelectedIndex = Global.Modes.IndexOf((Models.Mode)ModeComboBox.SelectedItem);
} }
catch catch
{ {
@@ -721,7 +721,7 @@ namespace Netch.Forms
return; return;
} }
var mode = (Models.Mode) ModeComboBox.SelectedItem; var mode = (Models.Mode)ModeComboBox.SelectedItem;
if (ModifierKeys == Keys.Control) if (ModifierKeys == Keys.Control)
{ {
Utils.Utils.Open(ModeHelper.GetFullPath(mode.RelativePath!)); Utils.Utils.Open(ModeHelper.GetFullPath(mode.RelativePath!));
@@ -756,7 +756,7 @@ namespace Netch.Forms
return; return;
} }
ModeHelper.Delete((Models.Mode) ModeComboBox.SelectedItem); ModeHelper.Delete((Models.Mode)ModeComboBox.SelectedItem);
SelectLastMode(); SelectLastMode();
} }
@@ -773,7 +773,7 @@ namespace Netch.Forms
{ {
// Clear // Clear
foreach (var button in ProfileTable.Controls) foreach (var button in ProfileTable.Controls)
((Button) button).Dispose(); ((Button)button).Dispose();
ProfileTable.Controls.Clear(); ProfileTable.Controls.Clear();
ProfileTable.ColumnStyles.Clear(); ProfileTable.ColumnStyles.Clear();
@@ -799,7 +799,7 @@ namespace Netch.Forms
var columnCount = Global.Settings.ProfileTableColumnCount; var columnCount = Global.Settings.ProfileTableColumnCount;
ProfileTable.ColumnCount = profileCount >= columnCount ? columnCount : profileCount; 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) for (var i = 0; i < profileCount; ++i)
{ {
@@ -848,8 +848,8 @@ namespace Netch.Forms
private Profile CreateProfileAtIndex(int index) private Profile CreateProfileAtIndex(int index)
{ {
var server = (Server) ServerComboBox.SelectedItem; var server = (Server)ServerComboBox.SelectedItem;
var mode = (Models.Mode) ModeComboBox.SelectedItem; var mode = (Models.Mode)ModeComboBox.SelectedItem;
var name = ProfileNameText.Text; var name = ProfileNameText.Text;
Profile? profile; Profile? profile;
@@ -866,8 +866,8 @@ namespace Netch.Forms
if (sender == null) if (sender == null)
throw new ArgumentNullException(nameof(sender)); throw new ArgumentNullException(nameof(sender));
var profileButton = (Button) sender; var profileButton = (Button)sender;
var profile = (Profile?) profileButton.Tag; var profile = (Profile?)profileButton.Tag;
var index = ProfileTable.Controls.IndexOf(profileButton); var index = ProfileTable.Controls.IndexOf(profileButton);
switch (ModifierKeys) switch (ModifierKeys)
@@ -1107,13 +1107,13 @@ namespace Netch.Forms
{ {
NatTypeStatusLightLabel.Visible = Flags.IsWindows10Upper; NatTypeStatusLightLabel.Visible = Flags.IsWindows10Upper;
var c = natType switch var c = natType switch
{ {
1 => Color.LimeGreen, 1 => Color.LimeGreen,
2 => Color.Yellow, 2 => Color.Yellow,
3 => Color.Red, 3 => Color.Red,
4 => Color.Black, 4 => Color.Black,
_ => throw new ArgumentOutOfRangeException(nameof(natType), natType, null) _ => throw new ArgumentOutOfRangeException(nameof(natType), natType, null)
}; };
NatTypeStatusLightLabel.ForeColor = c; NatTypeStatusLightLabel.ForeColor = c;
} }
@@ -1178,7 +1178,7 @@ namespace Netch.Forms
if (!IsWaiting()) if (!IsWaiting())
{ {
_resumeFlag = true; _resumeFlag = true;
Logging.Info("操作系统即将挂起,自动停止"); Global.Logger.Info("操作系统即将挂起,自动停止");
ControlButton_Click(null, null); ControlButton_Click(null, null);
} }
@@ -1187,7 +1187,7 @@ namespace Netch.Forms
if (_resumeFlag) if (_resumeFlag)
{ {
_resumeFlag = false; _resumeFlag = false;
Logging.Info("操作系统即将从挂起状态继续,自动重启"); Global.Logger.Info("操作系统即将从挂起状态继续,自动重启");
ControlButton_Click(null, null); ControlButton_Click(null, null);
} }
@@ -1231,7 +1231,7 @@ namespace Netch.Forms
Configuration.Save(); 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)) if (File.Exists(file))
File.Delete(file); File.Delete(file);
@@ -1401,38 +1401,38 @@ namespace Netch.Forms
switch (cbx.Items[e.Index]) switch (cbx.Items[e.Index])
{ {
case Server item: 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, TextRenderer.DrawText(e.Graphics,
item.Delay.ToString(), item.Delay.ToString(),
cbx.Font, cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y), new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black, Color.Black,
TextFormatFlags.Left); TextFormatFlags.Left);
break; break;
} }
case Models.Mode item: case Models.Mode item:
{ {
// 绘制 模式Box 底色 // 绘制 模式Box 底色
e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height); e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
// 绘制 模式行数 字符串 // 绘制 模式行数 字符串
TextRenderer.DrawText(e.Graphics, TextRenderer.DrawText(e.Graphics,
item.Rule.Count.ToString(), item.Rule.Count.ToString(),
cbx.Font, cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y), new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black, Color.Black,
TextFormatFlags.Left); TextFormatFlags.Left);
break; break;
} }
} }
} }

View File

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

View File

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

View File

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

View File

@@ -1,13 +1,13 @@
#nullable disable #nullable disable
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms namespace Netch.Forms
{ {
@@ -38,13 +38,13 @@ namespace Netch.Forms
InitializeComponent(); InitializeComponent();
_checkActions.Add(RemarkTextBox, s => true); _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); _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); _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; } protected abstract string TypeName { get; }
@@ -99,7 +99,7 @@ namespace Netch.Forms
}; };
_checkActions.Add(textBox, check); _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[] ConfigurationGroupBox.Controls.AddRange(new Control[]
{ {
textBox, textBox,
@@ -131,7 +131,7 @@ namespace Netch.Forms
comboBox.Items.AddRange(values.ToArray()); comboBox.Items.AddRange(values.ToArray());
comboBox.SelectedIndex = values.IndexOf(value); comboBox.SelectedIndex = values.IndexOf(value);
comboBox.DrawItem += Utils.Utils.DrawCenterComboBox; 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[] ConfigurationGroupBox.Controls.AddRange(new Control[]
{ {
comboBox, comboBox,
@@ -159,7 +159,7 @@ namespace Netch.Forms
Text = remark Text = remark
}; };
_saveActions.Add(checkBox, o => save.Invoke((bool) o)); _saveActions.Add(checkBox, o => save.Invoke((bool)o));
ConfigurationGroupBox.Controls.AddRange(new Control[] ConfigurationGroupBox.Controls.AddRange(new Control[]
{ {
checkBox checkBox

View File

@@ -1,3 +1,6 @@
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
@@ -5,9 +8,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Windows.Forms; using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms namespace Netch.Forms
{ {
@@ -37,7 +37,7 @@ namespace Netch.Forms
BindCheckBox(AllowDevicesCheckBox, BindCheckBox(AllowDevicesCheckBox,
c => Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1", 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); BindCheckBox(ResolveServerHostnameCheckBox, c => Global.Settings.ResolveServerHostname = c, Global.Settings.ResolveServerHostname);
@@ -63,7 +63,7 @@ namespace Netch.Forms
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Warning($"Load stun.txt failed: {e.Message}"); Global.Logger.Warning($"Load stun.txt failed: {e.Message}");
stuns = null; stuns = null;
} }
@@ -116,7 +116,7 @@ namespace Netch.Forms
Global.Settings.Redirector.ChildProcessHandle); Global.Settings.Redirector.ChildProcessHandle);
BindListComboBox(ProcessProxyProtocolComboBox, 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)), Enum.GetNames(typeof(PortType)),
Global.Settings.Redirector.ProxyProtocol.ToString()); Global.Settings.Redirector.ProxyProtocol.ToString());
@@ -284,7 +284,7 @@ namespace Netch.Forms
{ {
try try
{ {
return check.Invoke((T) Convert.ChangeType(s, typeof(T))); return check.Invoke((T)Convert.ChangeType(s, typeof(T)));
} }
catch 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) private void BindCheckBox(CheckBox control, Action<bool> save, bool value)
{ {
control.Checked = 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) private void BindRadioBox(RadioButton control, Action<bool> save, bool value)
{ {
control.Checked = 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 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.ValueMember = nameof(TagItem<T>.Value);
comboBox.DisplayMember = nameof(TagItem<T>.Text); 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)); }; Load += (_, _) => { comboBox.SelectedItem = tagItems.SingleOrDefault(t => t.Value.Equals(value)); };
} }
@@ -327,7 +327,7 @@ namespace Netch.Forms
if (values != null) if (values != null)
control.Items.AddRange(values); 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); _checkActions.Add(control, check.Invoke);
Load += (_, _) => { control.Text = value; }; Load += (_, _) => { control.Text = value; };

View File

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

View File

@@ -1,10 +1,12 @@
using Netch.Forms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Loggers;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Text.Json; using System.Text.Json;
using System.Windows.Forms; using System.Windows.Forms;
using Netch.Forms;
using Netch.Models;
namespace Netch namespace Netch
{ {
@@ -25,6 +27,22 @@ namespace Netch
/// </summary> /// </summary>
public static readonly List<Mode> Modes = new(); public static readonly List<Mode> Modes = new();
public static readonly string NetchDir;
public static readonly string NetchExecutable;
static Global()
{
NetchExecutable = Application.ExecutablePath;
NetchDir = Application.StartupPath;
#if DEBUG
Logger = new ConsoleLogger();
#else
Logger = new FileLogger();
#endif
}
public static ILogger Logger { get; }
/// <summary> /// <summary>
/// 主窗体的静态实例 /// 主窗体的静态实例
/// </summary> /// </summary>
@@ -36,8 +54,5 @@ namespace Netch
IgnoreNullValues = true, IgnoreNullValues = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}; };
public static readonly string NetchDir = Application.StartupPath;
public static readonly string NetchExecutable = Application.ExecutablePath;
} }
} }

View File

@@ -0,0 +1,11 @@
namespace Netch.Interfaces
{
public interface ILogger
{
void Info(string text);
void Warning(string text);
void Error(string text);
void Debug(string s);
void ShowLog();
}
}

15
Netch/Interops/NFAPI.cs Normal file
View File

@@ -0,0 +1,15 @@
using System.Runtime.InteropServices;
namespace Netch.Interops
{
public static class NFAPI
{
private const string nfapinet_bin = "nfapinet.dll";
[DllImport(nfapinet_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern NF_STATUS nf_registerDriver(string driverName);
[DllImport(nfapinet_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern NF_STATUS nf_unRegisterDriver(string driverName);
}
}

View File

@@ -0,0 +1,11 @@
namespace Netch.Interops
{
public enum NF_STATUS : int
{
NF_STATUS_SUCCESS = 0,
NF_STATUS_FAIL = -1,
NF_STATUS_INVALID_ENDPOINT_ID = -2,
NF_STATUS_NOT_INITIALIZED = -3,
NF_STATUS_IO_ERROR = -4
}
}

View File

@@ -1,5 +1,4 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Netch.Utils;
namespace Netch.Interops namespace Netch.Interops
{ {
@@ -7,12 +6,15 @@ namespace Netch.Interops
{ {
public enum NameList public enum NameList
{ {
TYPE_FILTLOP, TYPE_FILTERLOOPBACK,
TYPE_FILTTCP, TYPE_FILTERICMP,
TYPE_FILTUDP, TYPE_FILTERTCP,
TYPE_FILTERUDP,
TYPE_CLRNAME, TYPE_CLRNAME,
TYPE_ADDNAME, TYPE_ADDNAME,
TYPE_BYPNAME, TYPE_BYPNAME,
TYPE_DNSHOST, TYPE_DNSHOST,
TYPE_TCPLISN, TYPE_TCPLISN,
@@ -40,7 +42,7 @@ namespace Netch.Interops
public static bool Dial(NameList name, string value) public static bool Dial(NameList name, string value)
{ {
Logging.Debug($"Dial {name} {value}"); Global.Logger.Debug($"Dial {name} {value}");
return aio_dial(name, value); return aio_dial(name, value);
} }
@@ -54,7 +56,7 @@ namespace Netch.Interops
return aio_free(); 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"; private const string Redirector_bin = "Redirector.bin";

View File

@@ -1,6 +1,5 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Netch.Utils;
namespace Netch.Interops namespace Netch.Interops
{ {
@@ -36,7 +35,7 @@ namespace Netch.Interops
public static bool Dial(NameList name, string value) public static bool Dial(NameList name, string value)
{ {
Logging.Debug($"Dial {name} {value}"); Global.Logger.Debug($"Dial {name} {value}");
return tun_dial(name, Encoding.UTF8.GetBytes(value)); return tun_dial(name, Encoding.UTF8.GetBytes(value));
} }
@@ -62,7 +61,7 @@ namespace Netch.Interops
private static extern bool tun_free(); private static extern bool tun_free();
[DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern ulong tun_luid(); public static extern ulong tun_luid();
[DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern ulong tun_getUP(); private static extern ulong tun_getUP();

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions;
namespace Netch.Models.GitHubRelease namespace Netch.Models.GitHubRelease
{ {
@@ -8,28 +9,53 @@ namespace Netch.Models.GitHubRelease
{ {
public Version Version { get; } 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; Version = version;
Suffix = suffix; Suffix = suffix;
SuffixNum = suffixNum;
} }
public static SuffixVersion Parse(string? input) public static SuffixVersion Parse(string? value)
{ {
if (input == null) if (value == null)
throw new ArgumentNullException(nameof(input)); throw new ArgumentNullException(nameof(value));
var split = input.Split('-'); var strings = value.Split('-');
var dotNetVersion = Version.Parse(split[0]);
var preRelease = split.ElementAtOrDefault(1) ?? string.Empty;
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 try
{ {
result = Parse(input); result = Parse(input);
@@ -37,7 +63,6 @@ namespace Netch.Models.GitHubRelease
} }
catch (Exception) catch (Exception)
{ {
result = default;
return false; return false;
} }
} }
@@ -62,21 +87,22 @@ namespace Netch.Models.GitHubRelease
if (versionComparison != 0) if (versionComparison != 0)
return versionComparison; return versionComparison;
if (Suffix == string.Empty) var suffixExistComparison = (Suffix != null ? 1 : 0) - (other.Suffix != null ? 1 : 0);
return other.Suffix == string.Empty ? 0 : 1; if (suffixExistComparison != 0)
return suffixExistComparison;
if (other.Suffix == string.Empty)
return -1;
var suffixComparison = string.Compare(Suffix, other.Suffix, StringComparison.OrdinalIgnoreCase); var suffixComparison = string.Compare(Suffix, other.Suffix, StringComparison.OrdinalIgnoreCase);
return suffixComparison; if (suffixComparison != 0)
return suffixComparison;
return SuffixNum - other.SuffixNum;
} }
public override string ToString() public override string ToString()
{ {
var s = Version.ToString(); var s = Version.ToString();
if (Suffix != string.Empty) if (Suffix != null)
s += $"-{Suffix}"; s += $"-{Suffix}{SuffixNum}";
return s; 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; using System.Linq;
namespace Netch.Models.GitHubRelease namespace Netch.Models.GitHubRelease
{ {
public static class VersionUtil public static class VersionUtil
{ {
public static Release GetLatestRelease(IEnumerable<Release> releases, bool isPreRelease) private static VersionComparer instance = new();
{
if (!isPreRelease)
releases = releases.Where(release => !release.prerelease);
releases = releases.Where(release => IsVersionString(release.tag_name)); public static int CompareVersion(string x, string y)
var ordered = releases.OrderByDescending(release => release.tag_name, new VersionComparer()); {
return ordered.ElementAt(0); 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> var parseResult = xResult - yResult;
/// <returns> &gt;0:version1 is greater</returns> if (parseResult != 0)
/// <returns> &lt;0:version2 is greater</returns> return parseResult;
public static int CompareVersion(string? v1, string? v2)
{ return version1.CompareTo(version2);
var version1 = SuffixVersion.Parse(v1); }
var version2 = SuffixVersion.Parse(v2);
return version1.CompareTo(version2);
} }
} }
} }

View File

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

View File

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

View File

@@ -0,0 +1,52 @@
using Netch.Interfaces;
using System;
namespace Netch.Models.Loggers
{
public class ConsoleLogger : ILogger
{
public void Info(string text)
{
Write(text, LogLevel.INFO);
}
public void Warning(string text)
{
Write(text, LogLevel.WARNING);
}
public void Error(string text)
{
Write(text, LogLevel.ERROR);
}
private void Write(string text, LogLevel logLevel)
{
var contents = $@"[{DateTime.Now}][{logLevel.ToString()}] {text}{Constants.EOF}";
switch (logLevel)
{
case LogLevel.DEBUG:
case LogLevel.INFO:
case LogLevel.WARNING:
Console.Write(contents);
break;
case LogLevel.ERROR:
Console.Error.Write(contents);
break;
default:
throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null);
}
}
public void Debug(string s)
{
#if DEBUG
Write(s, LogLevel.DEBUG);
#endif
}
public void ShowLog()
{
}
}
}

View File

@@ -0,0 +1,48 @@
using Netch.Interfaces;
using System;
using System.IO;
namespace Netch.Models.Loggers
{
public class FileLogger : ILogger
{
public string LogFile { get; set; } = Path.Combine(Global.NetchDir, "logging\\application.log");
private readonly object _fileLock = new();
public void Info(string text)
{
Write(text, LogLevel.INFO);
}
public void Warning(string text)
{
Write(text, LogLevel.WARNING);
}
public void Error(string text)
{
Write(text, LogLevel.ERROR);
}
public void Write(string text, LogLevel logLevel)
{
var contents = $@"[{DateTime.Now}][{logLevel.ToString()}] {text}{Constants.EOF}";
lock (_fileLock)
File.AppendAllText(LogFile, contents);
}
public void Debug(string s)
{
#if DEBUG
Write(s, LogLevel.DEBUG);
#endif
}
public void ShowLog()
{
Utils.Utils.Open(LogFile);
}
}
}

View File

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

View File

@@ -2,7 +2,6 @@
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using Netch.Utils;
using Vanara.PInvoke; using Vanara.PInvoke;
namespace Netch.Models namespace Netch.Models
@@ -22,21 +21,19 @@ namespace Netch.Models
ni.GetIPProperties().GetIPv4Properties().Index == pRoute.dwForwardIfIndex); ni.GetIPProperties().GetIPv4Properties().Index == pRoute.dwForwardIfIndex);
Address = new IPAddress(pRoute.dwForwardNextHop.S_addr); Address = new IPAddress(pRoute.dwForwardNextHop.S_addr);
InterfaceIndex = (int) pRoute.dwForwardIfIndex; InterfaceIndex = (ulong)pRoute.dwForwardIfIndex;
Gateway = new IPAddress(pRoute.dwForwardNextHop.S_un_b); Gateway = new IPAddress(pRoute.dwForwardNextHop.S_un_b);
Logging.Info($"出口 网关 地址:{Gateway}"); Global.Logger.Info($"出口 网关 地址:{Gateway}");
Logging.Info($"出口适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {InterfaceIndex}"); Global.Logger.Info($"出口适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {InterfaceIndex}");
} }
public IPAddress Address { get; set; } public IPAddress Address { get; }
public string AdapterId => throw new NotImplementedException();
/// <summary> /// <summary>
/// 索引 /// 索引
/// </summary> /// </summary>
public int InterfaceIndex { get; } public ulong InterfaceIndex { get; }
/// <summary> /// <summary>
/// 网关 /// 网关

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Netch.Utils;
namespace Netch.Models namespace Netch.Models
{ {
@@ -49,7 +48,7 @@ namespace Netch.Models
case bool b: case bool b:
return b ? $"{prefix}{key}" : null; return b ? $"{prefix}{key}" : null;
default: default:
if ((value?.ToString() ?? null).IsNullOrWhiteSpace()) if (string.IsNullOrWhiteSpace(value?.ToString()))
return p.IsDefined(typeof(OptionalAttribute)) ? null : throw new RequiredArgumentValueInvalidException(p.Name, this, null); return p.IsDefined(typeof(OptionalAttribute)) ? null : throw new RequiredArgumentValueInvalidException(p.Name, this, null);
if (p.IsDefined(typeof(QuoteAttribute))) if (p.IsDefined(typeof(QuoteAttribute)))

View File

@@ -1,8 +1,8 @@
using System; using Netch.Utils;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Threading.Tasks; using System.Threading.Tasks;
using Netch.Utils;
namespace Netch.Models 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 namespace Netch.Models
{ {
@@ -265,7 +265,7 @@ namespace Netch.Models
public Setting Clone() public Setting Clone()
{ {
return (Setting) MemberwiseClone(); return (Setting)MemberwiseClone();
} }
public void Set(Setting value) public void Set(Setting value)

View File

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

View File

@@ -1,33 +1,26 @@
using System; using Netch.Interops;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using Netch.Controllers;
using Netch.Interops;
using Netch.Utils;
namespace Netch.Models namespace Netch.Models
{ {
public class TunAdapter : IAdapter public class TunAdapter : IAdapter
{ {
private const string ComponentIdWintun = "wintun";
public TunAdapter() public TunAdapter()
{ {
AdapterId = AdapterUtils.GetAdapterId(ComponentIdWintun) ?? throw new Exception("wintun adapter not found"); InterfaceIndex = NativeMethods.ConvertLuidToIndex(TUNInterop.tun_luid());
NetworkInterface = NetworkInterface.GetAllNetworkInterfaces().First(i => i.Id == AdapterId); NetworkInterface = NetworkInterface.GetAllNetworkInterfaces().First(i => i.GetIPProperties().GetIPv4Properties().Index == (int)InterfaceIndex);
InterfaceIndex = NetworkInterface.GetIPProperties().GetIPv4Properties().Index;
Gateway = IPAddress.Parse(Global.Settings.TUNTAP.Gateway); Gateway = IPAddress.Parse(Global.Settings.TUNTAP.Gateway);
Logging.Info($"WinTUN 适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {InterfaceIndex}"); Global.Logger.Info($"WinTUN 适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {InterfaceIndex}");
} }
public string AdapterId { get; set; }
public int InterfaceIndex { get; } public ulong InterfaceIndex { get; }
public IPAddress Gateway { get; } public IPAddress Gateway { get; }
public NetworkInterface NetworkInterface { get; } public NetworkInterface NetworkInterface { get; }
} }
} }

View File

@@ -1,47 +1,29 @@
using System.Runtime.InteropServices; using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Netch namespace Netch
{ {
public static class NativeMethods 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")] [DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
public static extern uint FlushDNSResolverCache(); public static extern uint RefreshDNSCache();
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern ulong ConvertLuidToIndex(ulong id);
[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.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using Netch.Controllers;
using Netch.Forms;
using Netch.Utils;
using static Vanara.PInvoke.Kernel32; using static Vanara.PInvoke.Kernel32;
namespace Netch namespace Netch
@@ -41,7 +41,7 @@ namespace Netch
Updater.Updater.CleanOld(Global.NetchDir); 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) foreach (var item in directories)
if (!Directory.Exists(item)) if (!Directory.Exists(item))
Directory.CreateDirectory(item); Directory.CreateDirectory(item);
@@ -80,8 +80,8 @@ namespace Netch
Environment.Exit(2); Environment.Exit(2);
} }
Logging.Info($"版本: {UpdateChecker.Owner}/{UpdateChecker.Repo}@{UpdateChecker.Version}"); Global.Logger.Info($"版本: {UpdateChecker.Owner}/{UpdateChecker.Repo}@{UpdateChecker.Version}");
Task.Run(() => { Logging.Info($"主程序 SHA256: {Utils.Utils.SHA256CheckSum(Global.NetchExecutable)}"); }); Task.Run(() => { Global.Logger.Info($"主程序 SHA256: {Utils.Utils.SHA256CheckSum(Global.NetchExecutable)}"); });
// 绑定错误捕获 // 绑定错误捕获
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
@@ -101,8 +101,8 @@ namespace Netch
public static void Application_OnException(object sender, ThreadExceptionEventArgs e) public static void Application_OnException(object sender, ThreadExceptionEventArgs e)
{ {
Logging.Error(e.Exception.ToString()); Global.Logger.Error(e.Exception.ToString());
Utils.Utils.Open(Logging.LogFile); Global.Logger.ShowLog();
} }
private static void SingleInstance_ArgumentsReceived(IEnumerable<string> args) private static void SingleInstance_ArgumentsReceived(IEnumerable<string> args)

View File

@@ -1,45 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows7</TargetFramework>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<StartupObject>Netch.Netch</StartupObject> <StartupObject>Netch.Netch</StartupObject>
<ApplicationManifest>App.manifest</ApplicationManifest> <ApplicationManifest>App.manifest</ApplicationManifest>
<ApplicationIcon>Resources\Netch.ico</ApplicationIcon> <ApplicationIcon>Resources\Netch.ico</ApplicationIcon>
<Platforms>x64</Platforms>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<LangVersion>latest</LangVersion>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<EnableNETAnalyzers>false</EnableNETAnalyzers> <EnableNETAnalyzers>false</EnableNETAnalyzers>
<AnalysisMode>Default</AnalysisMode> <AnalysisMode>Default</AnalysisMode>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors> <CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<TargetFramework>net5.0-windows</TargetFramework>
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
<Configurations>Debug;Release</Configurations>
<Platforms>x64</Platforms>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutputPath>bin\x64\Debug\</OutputPath> <OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors />
<NoWarn />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NoWarn />
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors />
<OutputPath>bin\x64\Release\</OutputPath> <OutputPath>bin\x64\Release\</OutputPath>
<DebugType>none</DebugType> <DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols> <DebugSymbols>false</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Remove=".gitignore" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="HMBSbige.SingleInstance" Version="5.0.0" /> <PackageReference Include="HMBSbige.SingleInstance" Version="5.0.0" />
<PackageReference Include="MaxMind.GeoIP2" Version="4.0.1" /> <PackageReference Include="MaxMind.GeoIP2" Version="4.0.1" />
@@ -50,25 +45,14 @@
</PackageReference> </PackageReference>
<PackageReference Include="System.Drawing.Common" Version="5.0.2" /> <PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<PackageReference Include="TaskScheduler" Version="2.9.1" /> <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="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="WindowsFirewallHelper" Version="2.0.4.70-beta2" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="5.0.0" /> <PackageReference Include="System.ServiceProcess.ServiceController" Version="5.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Interop.nfapinet\Interop.nfapinet.csproj" />
</ItemGroup>
<ItemGroup>
<None Visible="false" Include="..\binaries\**" LinkBase="bin" CopyToPublishDirectory="PreserveNewest" CopyToOutputDirectory="PreserveNewest" />
<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> <ItemGroup>
<Compile Update="Properties\Resources.Designer.cs"> <Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
@@ -96,14 +80,6 @@
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None> </None>
</ItemGroup> </ItemGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties />
</VisualStudio>
</ProjectExtensions>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="set TargetFramework=$(TargetFramework)&#xD;&#xA;set Configuration=$(Configuration)&#xD;&#xA;set ILMergeConsolePath=$(ILMergeConsolePath)&#xD;&#xA;set TargetDir=$(TargetDir)&#xD;&#xA;set SolutionDir=$(SolutionDir)&#xD;&#xA;call $(ProjectDir)PostBuild.bat" />
</Target>
<Target Condition="'$(PublishSingleFile)' == 'true'" AfterTargets="_ComputeFilesToBundle" Name="RemoveDupeAssemblies"> <Target Condition="'$(PublishSingleFile)' == 'true'" AfterTargets="_ComputeFilesToBundle" Name="RemoveDupeAssemblies">
<ItemGroup> <ItemGroup>
@@ -112,5 +88,4 @@
<_FilesToBundle Remove="$(PkgMicrosoft_Diagnostics_Tracing_TraceEvent)\lib\netstandard1.6\TraceReloggerLib.dll" /> <_FilesToBundle Remove="$(PkgMicrosoft_Diagnostics_Tracing_TraceEvent)\lib\netstandard1.6\TraceReloggerLib.dll" />
</ItemGroup> </ItemGroup>
</Target> </Target>
</Project> </Project>

View File

@@ -1,20 +0,0 @@
if %Configuration%==Release if %TargetFramework%==net48 (
:: Merge dlls
%ILMergeConsolePath% /wildcards /out:%TargetDir%Netch.exe ^
/lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319" ^
/targetplatform:v4,"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8" ^
%TargetDir%Netch.exe ^
%TargetDir%*.dll
DEL /f %TargetDir%*.dll >NUL 2>&1
)
if %Configuration%==Release (
DEL /f %TargetDir%*.config >NUL 2>&1
DEL /f %TargetDir%*.pdb >NUL 2>&1
)
RD /s /Q %TargetDir%x86 >NUL 2>&1
RD /s /Q %TargetDir%de %TargetDir%es %TargetDir%fr %TargetDir%it %TargetDir%pl %TargetDir%ru %TargetDir%zh-CN >NUL 2>&1
exit 0

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Netch.Controllers; using Netch.Controllers;
using Netch.Models; using Netch.Models;
using System.Collections.Generic;
namespace Netch.Servers.ShadowsocksR namespace Netch.Servers.ShadowsocksR
{ {
@@ -8,9 +8,9 @@ namespace Netch.Servers.ShadowsocksR
{ {
public override string MainFile { get; protected set; } = "ShadowsocksR.exe"; 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"; public override string Name { get; } = "ShadowsocksR";
@@ -20,7 +20,7 @@ namespace Netch.Servers.ShadowsocksR
public void Start(in Server s, in Mode mode) public void Start(in Server s, in Mode mode)
{ {
var server = (ShadowsocksR) s; var server = (ShadowsocksR)s;
var command = new SSRParameter var command = new SSRParameter
{ {

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic; using Netch.Controllers;
using System.IO;
using System.Text.Json;
using Netch.Controllers;
using Netch.Models; using Netch.Models;
using Netch.Servers.Trojan.Models; using Netch.Servers.Trojan.Models;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
namespace Netch.Servers.Trojan namespace Netch.Servers.Trojan
{ {
@@ -11,9 +11,9 @@ namespace Netch.Servers.Trojan
{ {
public override string MainFile { get; protected set; } = "Trojan.exe"; 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"; public override string Name { get; } = "Trojan";
@@ -23,7 +23,7 @@ namespace Netch.Servers.Trojan
public void Start(in Server s, in Mode mode) public void Start(in Server s, in Mode mode)
{ {
var server = (Trojan) s; var server = (Trojan)s;
var trojanConfig = new TrojanConfig var trojanConfig = new TrojanConfig
{ {
local_addr = this.LocalAddress(), 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Web; using System.Web;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Trojan.Form;
namespace Netch.Servers.Trojan namespace Netch.Servers.Trojan
{ {
@@ -18,13 +18,13 @@ namespace Netch.Servers.Trojan
public string ShortName { get; } = "TR"; public string ShortName { get; } = "TR";
public string[] UriScheme { get; } = {"trojan"}; public string[] UriScheme { get; } = { "trojan" };
public Type ServerType { get; } = typeof(Trojan); public Type ServerType { get; } = typeof(Trojan);
public void Edit(Server s) public void Edit(Server s)
{ {
new TrojanForm((Trojan) s).ShowDialog(); new TrojanForm((Trojan)s).ShowDialog();
} }
public void Create() public void Create()
@@ -34,7 +34,7 @@ namespace Netch.Servers.Trojan
public string GetShareLink(Server s) 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}"; 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.Hostname = match.Groups["server"].Value;
data.Port = ushort.Parse(match.Groups["port"].Value); data.Port = ushort.Parse(match.Groups["port"].Value);
return new[] {data}; return new[] { data };
} }
public bool CheckServer(Server s) 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.Linq;
using System.Text.Json; using System.Text.Json;
using Netch.Models;
using Netch.Servers.V2ray.Models;
using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig; using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig;
namespace Netch.Servers.V2ray.Utils namespace Netch.Servers.V2ray.Utils
@@ -109,8 +109,8 @@ namespace Netch.Servers.V2ray.Utils
switch (server) switch (server)
{ {
case Socks5.Socks5 socks5: case Socks5.Socks5 socks5:
{ {
outbound.settings.servers = new List<ServersItem> outbound.settings.servers = new List<ServersItem>
{ {
new() 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.enabled = false;
outbound.mux.concurrency = -1; outbound.mux.concurrency = -1;
outbound.protocol = "socks";
break;
} }
else case VLESS.VLESS vless:
{ {
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux; var vnextItem = new VnextItem
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1; {
} users = new List<UsersItem>(),
address = server.AutoResolveHostname(),
port = server.Port
};
outbound.protocol = "vless"; outbound.settings.vnext = new List<VnextItem> { vnextItem };
outbound.settings.servers = null;
break; 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: case VMess.VMess vmess:
{
var vnextItem = new VnextItem
{ {
users = new List<UsersItem>(), var vnextItem = new VnextItem
address = server.AutoResolveHostname(), {
port = server.Port 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 var usersItem = new UsersItem
{ {
id = vmess.UserID, id = vmess.UserID,
alterId = vmess.AlterID, alterId = vmess.AlterID,
security = vmess.EncryptMethod security = vmess.EncryptMethod
}; };
vnextItem.users.Add(usersItem); vnextItem.users.Add(usersItem);
var streamSettings = outbound.streamSettings; var streamSettings = outbound.streamSettings;
boundStreamSettings(vmess, ref streamSettings); boundStreamSettings(vmess, ref streamSettings);
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux; outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1; outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
outbound.protocol = "vmess"; outbound.protocol = "vmess";
break; break;
} }
} }
v2rayConfig.outbounds.AddRange(new[] v2rayConfig.outbounds.AddRange(new[]
@@ -274,7 +274,7 @@ namespace Netch.Servers.V2ray.Utils
case "ws": case "ws":
var wsSettings = new WsSettings 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 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.Controllers;
using Netch.Models; using Netch.Models;
using Netch.Servers.V2ray.Utils; using Netch.Servers.V2ray.Utils;
using System.Collections.Generic;
using System.IO;
namespace Netch.Servers.V2ray namespace Netch.Servers.V2ray
{ {
@@ -10,9 +10,9 @@ namespace Netch.Servers.V2ray
{ {
public override string MainFile { get; protected set; } = "xray.exe"; 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"; public override string Name { get; } = "Xray";

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Netch.Forms; using Netch.Forms;
using System.Collections.Generic;
namespace Netch.Servers.VLESS.VLESSForm 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); CreateTextBox("QUICSecret", "QUIC Secret", s => true, s => server.QUICSecret = s, server.QUICSecret);
CreateComboBox("UseMux", CreateComboBox("UseMux",
"Use Mux", "Use Mux",
new List<string> {"", "true", "false"}, new List<string> { "", "true", "false" },
s => server.UseMux = s switch {"" => null, "true" => true, "false" => false, _ => null}, s => server.UseMux = s switch { "" => null, "true" => true, "false" => false, _ => null },
server.UseMux?.ToString().ToLower() ?? ""); server.UseMux?.ToString().ToLower() ?? "");
CreateComboBox("TLSSecure", "TLS Secure", VLESSGlobal.TLSSecure, s => server.TLSSecureType = s, server.TLSSecureType); 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.Controllers;
using Netch.Models; using Netch.Models;
using Netch.Servers.V2ray; using Netch.Servers.V2ray;
using System;
using System.Collections.Generic;
namespace Netch.Servers.VLESS namespace Netch.Servers.VLESS
{ {
@@ -16,13 +16,13 @@ namespace Netch.Servers.VLESS
public string ShortName { get; } = "VL"; public string ShortName { get; } = "VL";
public string[] UriScheme { get; } = {"vless"}; public string[] UriScheme { get; } = { "vless" };
public Type ServerType { get; } = typeof(VLESS); public Type ServerType { get; } = typeof(VLESS);
public void Edit(Server s) public void Edit(Server s)
{ {
new VLESSForm.VLESSForm((VLESS) s).ShowDialog(); new VLESSForm.VLESSForm((VLESS)s).ShowDialog();
} }
public void Create() 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 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); CreateTextBox("QUICSecret", "QUIC Secret", s => true, s => server.QUICSecret = s, server.QUICSecret);
CreateComboBox("UseMux", CreateComboBox("UseMux",
"Use Mux", "Use Mux",
new List<string> {"", "true", "false"}, new List<string> { "", "true", "false" },
s => server.UseMux = s switch {"" => null, "true" => true, "false" => false, _ => null}, s => server.UseMux = s switch { "" => null, "true" => true, "false" => false, _ => null },
server.UseMux?.ToString().ToLower() ?? ""); server.UseMux?.ToString().ToLower() ?? "");
CreateComboBox("TLSSecure", "TLS Secure", VMessGlobal.TLSSecure, s => server.TLSSecureType = s, server.TLSSecureType); 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 Netch.Models;
using System.Collections.Generic;
namespace Netch.Servers.VMess 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.Controllers;
using Netch.Models; using Netch.Models;
using Netch.Servers.V2ray; using Netch.Servers.V2ray;
using Netch.Servers.V2ray.Models; using Netch.Servers.V2ray.Models;
using Netch.Servers.VMess.Form; using Netch.Servers.VMess.Form;
using Netch.Utils; 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 namespace Netch.Servers.VMess
{ {
@@ -22,13 +22,13 @@ namespace Netch.Servers.VMess
public string ShortName { get; } = "V2"; public string ShortName { get; } = "V2";
public string[] UriScheme { get; } = {"vmess"}; public string[] UriScheme { get; } = { "vmess" };
public Type ServerType { get; } = typeof(VMess); public Type ServerType { get; } = typeof(VMess);
public void Edit(Server s) public void Edit(Server s)
{ {
new VMessForm((VMess) s).ShowDialog(); new VMessForm((VMess)s).ShowDialog();
} }
public void Create() public void Create()
@@ -40,22 +40,22 @@ namespace Netch.Servers.VMess
{ {
if (Global.Settings.V2RayConfig.V2rayNShareLink) if (Global.Settings.V2RayConfig.V2rayNShareLink)
{ {
var server = (VMess) s; var server = (VMess)s;
var vmessJson = JsonSerializer.Serialize(new V2rayNSharing var vmessJson = JsonSerializer.Serialize(new V2rayNSharing
{ {
v = 2, v = 2,
ps = server.Remark, ps = server.Remark,
add = server.Hostname, add = server.Hostname,
port = server.Port, port = server.Port,
id = server.UserID, id = server.UserID,
aid = server.AlterID, aid = server.AlterID,
net = server.TransferProtocol, net = server.TransferProtocol,
type = server.FakeType, type = server.FakeType,
host = server.Host, host = server.Host,
path = server.Path, path = server.Path,
tls = server.TLSSecureType tls = server.TLSSecureType
}, },
new JsonSerializerOptions new JsonSerializerOptions
{ {
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
@@ -87,7 +87,7 @@ namespace Netch.Servers.VMess
} }
V2rayNSharing vmess = JsonSerializer.Deserialize<V2rayNSharing>(s, 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.Remark = vmess.ps;
data.Hostname = vmess.add; data.Hostname = vmess.add;
@@ -114,7 +114,7 @@ namespace Netch.Servers.VMess
data.TLSSecureType = vmess.tls; data.TLSSecureType = vmess.tls;
data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个 data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个
return new[] {data}; return new[] { data };
} }
public bool CheckServer(Server s) 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
@@ -6,11 +10,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Windows.Threading;
using Netch.Controllers;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Updater namespace Netch.Updater
{ {
@@ -93,11 +92,10 @@ namespace Netch.Updater
#region Apply Update #region Apply Update
private static readonly ImmutableArray<string> KeepDirectories = new List<string> {"data", "mode\\Custom"}.ToImmutableArray(); private static readonly ImmutableArray<string> KeepDirectories = new List<string> { "data", "mode\\Custom", "logging" }.ToImmutableArray();
private void ApplyUpdate() private void ApplyUpdate()
{ {
var dispatcher = Dispatcher.CurrentDispatcher;
var mainForm = Global.MainForm; var mainForm = Global.MainForm;
#region PreUpdate #region PreUpdate
@@ -132,7 +130,7 @@ namespace Netch.Updater
MoveAllFilesOver(Path.Combine(extractPath, "Netch"), _installDirectory); MoveAllFilesOver(Path.Combine(extractPath, "Netch"), _installDirectory);
// release mutex, exit // release mutex, exit
dispatcher.Invoke(Netch.SingleInstance.Dispose); mainForm.Invoke(new Action(Netch.SingleInstance.Dispose));
Process.Start(Global.NetchExecutable); Process.Start(Global.NetchExecutable);
Environment.Exit(0); Environment.Exit(0);
} }
@@ -157,7 +155,15 @@ namespace Netch.Updater
// rename files // rename files
foreach (var file in filesToDelete) foreach (var file in filesToDelete)
File.Move(file, file + ".old"); try
{
File.Move(file, file + ".old");
}
catch
{
Global.Logger.Error($"failed to rename file \"{file}\"");
throw;
}
} }
private int Extract(string destDirName, bool overwrite) private int Extract(string destDirName, bool overwrite)

View File

@@ -1,48 +0,0 @@
using System;
using System.Linq;
using Microsoft.Win32;
namespace Netch.Utils
{
public static class AdapterUtils
{
public const string NETWORK_KEY = @"SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}";
public const string ADAPTER_KEY = @"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}";
/// <summary>
/// 获取 TUN/TAP 适配器名称
/// </summary>
/// <param name="componentId">适配器 ID</param>
/// <returns>适配器名称</returns>
public static string GetName(string componentId)
{
return Registry.LocalMachine.OpenSubKey($"{NETWORK_KEY}\\{componentId}\\Connection")?.GetValue("Name")?.ToString() ?? "";
}
public static string? GetAdapterId(params string[] componentIds)
{
try
{
var adaptersRegistry = Registry.LocalMachine.OpenSubKey(ADAPTER_KEY)!;
foreach (var keyName in adaptersRegistry.GetSubKeyNames().Where(s => s is not ("Configuration" or "Properties")))
{
var adapterRegistry = adaptersRegistry.OpenSubKey(keyName)!;
var componentId = adapterRegistry.GetValue("ComponentId")?.ToString();
if (componentId == null)
continue;
if (componentIds.Contains(componentId))
return (string) (adapterRegistry.GetValue("NetCfgInstanceId") ??
throw new Exception("Tap adapter have no NetCfgInstanceId key"));
}
}
catch (Exception e)
{
Logging.Warning(e.ToString());
}
return null;
}
}
}

View File

@@ -1,11 +1,11 @@
using System.Collections.Generic; using Microsoft.Diagnostics.Tracing.Parsers;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Session; using Microsoft.Diagnostics.Tracing.Session;
using Netch.Controllers; using Netch.Controllers;
using Netch.Models; using Netch.Models;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Netch.Utils namespace Netch.Utils
{ {
@@ -14,7 +14,7 @@ namespace Netch.Utils
public static ulong received; public static ulong received;
public static TraceEventSession? tSession; 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> /// <summary>
/// 计算流量 /// 计算流量
@@ -78,7 +78,7 @@ namespace Netch.Utils
var processList = instances.Select(instance => instance.Id).ToList(); var processList = instances.Select(instance => instance.Id).ToList();
Logging.Info("流量统计进程:" + string.Join(",", instances.Select(instance => $"({instance.Id})" + instance.ProcessName).ToArray())); Global.Logger.Info("流量统计进程:" + string.Join(",", instances.Select(instance => $"({instance.Id})" + instance.ProcessName).ToArray()));
received = 0; received = 0;
@@ -98,7 +98,7 @@ namespace Netch.Utils
{ {
if (processList.Contains(data.ProcessID)) if (processList.Contains(data.ProcessID))
lock (counterLock) lock (counterLock)
received += (ulong) data.size; received += (ulong)data.size;
// Debug.WriteLine($"TcpIpRecv: {ToByteSize(data.size)}"); // Debug.WriteLine($"TcpIpRecv: {ToByteSize(data.size)}");
}; };
@@ -107,7 +107,7 @@ namespace Netch.Utils
{ {
if (processList.Contains(data.ProcessID)) if (processList.Contains(data.ProcessID))
lock (counterLock) lock (counterLock)
received += (ulong) data.size; received += (ulong)data.size;
// Debug.WriteLine($"UdpIpRecv: {ToByteSize(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.IO;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Netch.Models;
namespace Netch.Utils namespace Netch.Utils
{ {
@@ -42,8 +42,8 @@ namespace Netch.Utils
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Error(e.ToString()); Global.Logger.Error(e.ToString());
Utils.Open(Logging.LogFile); Global.Logger.ShowLog();
Environment.Exit(-1); Environment.Exit(-1);
Global.Settings = null!; Global.Settings = null!;
} }

View File

@@ -17,7 +17,7 @@ namespace Netch.Utils
{ {
if (!FirewallWAS.IsSupported) if (!FirewallWAS.IsSupported)
{ {
Logging.Warning("不支持防火墙"); Global.Logger.Warning("不支持防火墙");
return; return;
} }
@@ -37,7 +37,7 @@ namespace Netch.Utils
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Warning("添加防火墙规则错误(如已关闭防火墙则可无视此错误)\n" + e); Global.Logger.Warning("添加防火墙规则错误(如已关闭防火墙则可无视此错误)\n" + e);
} }
} }
@@ -57,7 +57,7 @@ namespace Netch.Utils
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Warning("清除防火墙规则错误\n" + e); Global.Logger.Warning("清除防火墙规则错误\n" + e);
} }
} }

View File

@@ -1,70 +0,0 @@
using System;
using System.IO;
using Netch.Models;
namespace Netch.Utils
{
public static class Logging
{
public const string LogFile = "logging\\application.log";
private static readonly object FileLock = new();
/// <summary>
/// 信息
/// </summary>
/// <param name="text">内容</param>
public static void Info(string text)
{
Write(text, LogLevel.INFO);
}
/// <summary>
/// 信息
/// </summary>
/// <param name="text">内容</param>
public static void Warning(string text)
{
Write(text, LogLevel.WARNING);
}
/// <summary>
/// 错误
/// </summary>
/// <param name="text">内容</param>
public static void Error(string text)
{
Write(text, LogLevel.ERROR);
}
private static void Write(string text, LogLevel logLevel)
{
var contents = $@"[{DateTime.Now}][{logLevel.ToString()}] {text}{Constants.EOF}";
#if DEBUG
switch (logLevel)
{
case LogLevel.DEBUG:
case LogLevel.INFO:
case LogLevel.WARNING:
Console.Write(contents);
break;
case LogLevel.ERROR:
Console.Error.Write(contents);
break;
default:
throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null);
}
#else
lock (FileLock)
File.AppendAllText(LogFile, contents);
#endif
}
public static void Debug(string s)
{
#if DEBUG
Write(s, LogLevel.DEBUG);
#endif
}
}
}

View File

@@ -1,10 +1,10 @@
using System;
using System.IO;
using System.Linq;
using Netch.Controllers; using Netch.Controllers;
using Netch.Models; using Netch.Models;
using Netch.Servers.Shadowsocks; using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5; using Netch.Servers.Socks5;
using System;
using System.IO;
using System.Linq;
namespace Netch.Utils namespace Netch.Utils
{ {
@@ -85,7 +85,7 @@ namespace Netch.Utils
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Warning($"Load mode \"{file}\" failed: {e.Message}"); Global.Logger.Warning($"Load mode \"{file}\" failed: {e.Message}");
} }
} }
catch catch
@@ -113,11 +113,11 @@ namespace Netch.Utils
{ {
case 0: case 0:
return server switch return server switch
{ {
Socks5 => true, Socks5 => true,
Shadowsocks shadowsocks when !shadowsocks.HasPlugin() && Global.Settings.Redirector.RedirectorSS => true, Shadowsocks shadowsocks when !shadowsocks.HasPlugin() && Global.Settings.Redirector.RedirectorSS => true,
_ => false _ => false
}; };
case 1: case 1:
case 2: case 2:
return server is Socks5; 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) public static IModeController GetModeControllerByType(int type, out ushort? port, out string portName)
{ {
@@ -142,7 +142,7 @@ namespace Netch.Utils
case 6: case 6:
return new PcapController(); return new PcapController();
default: default:
Logging.Error("未知模式类型"); Global.Logger.Error("未知模式类型");
throw new MessageException("未知模式类型"); throw new MessageException("未知模式类型");
} }
} }

View File

@@ -24,7 +24,7 @@ namespace Netch.Utils
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Error("获取保留端口失败: " + e); Global.Logger.Error("获取保留端口失败: " + e);
} }
} }
@@ -33,9 +33,9 @@ namespace Netch.Utils
if (port == 0) if (port == 0)
throw new ArgumentOutOfRangeException(); 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) private static void GetReservedPortRange(PortType portType, ref List<Range> targetList)
@@ -143,7 +143,7 @@ namespace Netch.Utils
var random = new Random(); var random = new Random();
for (ushort i = 0; i < 55535; i++) for (ushort i = 0; i < 55535; i++)
{ {
var p = (ushort) random.Next(10000, 65535); var p = (ushort)random.Next(10000, 65535);
try try
{ {
CheckPort(p, portType); CheckPort(p, portType);

View File

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

View File

@@ -1,10 +1,10 @@
using Netch.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Timers; using System.Timers;
using Netch.Models;
using Range = Netch.Models.Range; using Range = Netch.Models.Range;
namespace Netch.Utils namespace Netch.Utils
@@ -17,7 +17,7 @@ namespace Netch.Utils
.GetExportedTypes() .GetExportedTypes()
.Where(type => type.GetInterfaces().Contains(typeof(IServerUtil))); .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) 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) private static bool ValueIsEnabled(int value)
{ {
@@ -74,7 +74,7 @@ namespace Netch.Utils
try try
{ {
_mux = true; _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; _mux = false;
TestDelayFinished?.Invoke(null, new EventArgs()); 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.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Shadowsocks.Models;
namespace Netch.Utils namespace Netch.Utils
{ {
@@ -32,17 +32,16 @@ namespace Netch.Utils
try try
{ {
list.AddRange(JsonSerializer.Deserialize<List<ShadowsocksConfig>>(text)! list.AddRange(JsonSerializer.Deserialize<List<ShadowsocksConfig>>(text)!.Select(server => new Shadowsocks
.Select(server => new Shadowsocks {
{ Hostname = server.server,
Hostname = server.server, Port = server.server_port,
Port = server.server_port, EncryptMethod = server.method,
EncryptMethod = server.method, Password = server.password,
Password = server.password, Remark = server.remarks,
Remark = server.remarks, Plugin = server.plugin,
Plugin = server.plugin, PluginOption = server.plugin_opts
PluginOption = server.plugin_opts }));
}));
} }
catch (JsonException) catch (JsonException)
{ {
@@ -56,16 +55,16 @@ namespace Netch.Utils
catch (Exception e) catch (Exception e)
{ {
errorFlag = true; errorFlag = true;
Logging.Error(e.ToString()); Global.Logger.Error(e.ToString());
} }
} }
if (errorFlag) if (errorFlag)
Utils.Open(Logging.LogFile); Global.Logger.ShowLog();
} }
catch (Exception e) catch (Exception e)
{ {
Logging.Error(e.ToString()); Global.Logger.Error(e.ToString());
} }
return list; return list;
@@ -90,7 +89,7 @@ namespace Netch.Utils
if (util != null) if (util != null)
list.AddRange(util.ParseUri(text)); list.AddRange(util.ParseUri(text));
else else
Logging.Warning($"无法处理 {scheme} 协议订阅链接"); Global.Logger.Warning($"无法处理 {scheme} 协议订阅链接");
} }
foreach (var node in list.Where(node => !node.Remark.IsNullOrWhiteSpace())) foreach (var node in list.Where(node => !node.Remark.IsNullOrWhiteSpace()))
@@ -123,7 +122,7 @@ namespace Netch.Utils
return JsonSerializer.Deserialize<Server>(text, return JsonSerializer.Deserialize<Server>(text,
new JsonSerializerOptions new JsonSerializerOptions
{ {
Converters = {new ServerConverterWithTypeDiscriminator()} Converters = { new ServerConverterWithTypeDiscriminator() }
})!; })!;
} }
@@ -159,7 +158,7 @@ namespace Netch.Utils
private static string RemoveEmoji(string text) private static string RemoveEmoji(string text)
{ {
byte[] emojiBytes = {240, 159}; byte[] emojiBytes = { 240, 159 };
var remark = Encoding.UTF8.GetBytes(text); var remark = Encoding.UTF8.GetBytes(text);
var startIndex = 0; var startIndex = 0;
while (remark.Length > startIndex + 1 && remark[startIndex] == emojiBytes[0] && remark[startIndex + 1] == emojiBytes[1]) 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(); var sb = new StringBuilder();
foreach (var t in value) foreach (var t in value)
{ {
var escapeCharacters = new[] {'\\', '*', '+', '?', '|', '{', '}', '[', ']', '(', ')', '^', '$', '.'}; var escapeCharacters = new[] { '\\', '*', '+', '?', '|', '{', '}', '[', ']', '(', ')', '^', '$', '.' };
if (escapeCharacters.Any(s => s == t)) if (escapeCharacters.Any(s => s == t))
sb.Append('\\'); sb.Append('\\');

View File

@@ -1,9 +1,9 @@
using Netch.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Netch.Models;
namespace Netch.Utils namespace Netch.Utils
{ {
@@ -53,7 +53,7 @@ namespace Netch.Utils
catch (Exception e) catch (Exception e)
{ {
Global.MainForm.NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false); Global.MainForm.NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false);
Logging.Error(e.ToString()); Global.Logger.Error(e.ToString());
} }
} }
} }

View File

@@ -1,3 +1,5 @@
using MaxMind.GeoIP2;
using Microsoft.Win32.TaskScheduler;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
@@ -11,8 +13,6 @@ using System.Security.Cryptography;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using MaxMind.GeoIP2;
using Microsoft.Win32.TaskScheduler;
using Task = System.Threading.Tasks.Task; using Task = System.Threading.Tasks.Task;
namespace Netch.Utils namespace Netch.Utils
@@ -105,8 +105,8 @@ namespace Netch.Utils
try try
{ {
var sha256 = SHA256.Create(); var sha256 = SHA256.Create();
var fileStream = File.OpenRead(filePath); using var fileStream = File.OpenRead(filePath);
return sha256.ComputeHash(fileStream).Aggregate(string.Empty, (current, b) => current + b.ToString("x2")); return string.Concat(sha256.ComputeHash(fileStream).Select(b => b.ToString("x2")));
} }
catch catch
{ {
@@ -219,8 +219,8 @@ namespace Netch.Utils
{ {
case TextBox _: case TextBox _:
case ComboBox _: case ComboBox _:
if (((Control) component).ForeColor != color) if (((Control)component).ForeColor != color)
((Control) component).ForeColor = color; ((Control)component).ForeColor = color;
break; break;
} }
@@ -243,7 +243,7 @@ namespace Netch.Utils
} }
}; };
Logging.Debug($"{fileName} {arguments}"); Global.Logger.Debug($"{fileName} {arguments}");
p.Start(); p.Start();
var output = await p.StandardOutput.ReadToEndAsync(); var output = await p.StandardOutput.ReadToEndAsync();

View File

@@ -19,7 +19,7 @@ namespace Netch.Utils
public static HttpWebRequest CreateRequest(string url, int? timeout = null, string? userAgent = null) 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.UserAgent = string.IsNullOrWhiteSpace(userAgent) ? DefaultUserAgent : userAgent;
req.Accept = "*/*"; req.Accept = "*/*";
req.KeepAlive = true; req.KeepAlive = true;
@@ -53,7 +53,7 @@ namespace Netch.Utils
/// <returns></returns> /// <returns></returns>
public static string DownloadString(HttpWebRequest req, out HttpWebResponse rep, string encoding = "UTF-8") 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 responseStream = rep.GetResponseStream();
using var streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encoding)); using var streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encoding));
@@ -83,7 +83,7 @@ namespace Netch.Utils
/// <returns></returns> /// <returns></returns>
public static async Task DownloadFileAsync(HttpWebRequest req, string fileFullPath) 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 input = webResponse.GetResponseStream();
await using var fileStream = File.OpenWrite(fileFullPath); 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.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@@ -6,7 +7,6 @@ using System.Linq;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Windows.Forms; using System.Windows.Forms;
using Netch.Properties;
namespace Netch.Utils namespace Netch.Utils
{ {
@@ -41,7 +41,7 @@ namespace Netch.Utils
{ {
var oldLangCode = LangCode; var oldLangCode = LangCode;
LangCode = languages.FirstOrDefault(s => GetLanguage(s).Equals(GetLanguage(LangCode))) ?? "en-US"; LangCode = languages.FirstOrDefault(s => GetLanguage(s).Equals(GetLanguage(LangCode))) ?? "en-US";
Logging.Info($"找不到语言 {oldLangCode}, 使用 {LangCode}"); Global.Logger.Info($"找不到语言 {oldLangCode}, 使用 {LangCode}");
} }
switch (LangCode) switch (LangCode)
@@ -61,7 +61,7 @@ namespace Netch.Utils
if (!dictionary.Any()) if (!dictionary.Any())
{ {
Logging.Error($"{LangCode} 语言文件错误"); Global.Logger.Error($"{LangCode} 语言文件错误");
return; return;
} }
@@ -99,14 +99,14 @@ namespace Netch.Utils
{ {
for (var i = 0; i < args.Length; i++) for (var i = 0; i < args.Length; i++)
if (args[i] is string) if (args[i] is string)
args[i] = Translate((string) args[i]); args[i] = Translate((string)args[i]);
return string.Format(Translate(format), args); return string.Format(Translate(format), args);
} }
public static List<string> GetTranslateList() 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")) if (!Directory.Exists("i18n"))
return translateFile; return translateFile;

View File

@@ -1,14 +0,0 @@
Write-Host 'Building'
dotnet publish -c "Release" `
-p:Platform="x64" `
-p:PublishSingleFile=true `
-p:RuntimeIdentifier=win-x64 `
-p:SolutionDir="$pwd\" `
-o Netch\bin\Publish\ `
--no-self-contained `
Netch\Netch.csproj
if ($LASTEXITCODE) { exit $LASTEXITCODE }
Write-Host 'Build done'

View File

@@ -17,10 +17,11 @@ Game network accelerator
- [Netch](#netch) - [Netch](#netch)
- [TOC](#toc) - [TOC](#toc)
- [Description](#description) - [Description](#description)
- [Sponsor](#sponsor) - [Sponsor](#sponsor)
- [Donate](#donate) - [Donate](#donate)
- [Screenshots](#screenshots) - [Screenshots](#screenshots)
- [Requirements](#requirements) - [Requirements](#requirements)
- [Quote](#quote)
## Description ## Description
Netch is an open source game network accelerator. Unlike SSTap, which needs to add rules to function as a blacklist proxy, Netch is more similar to SocksCap64, which can scan the game directory to get their process names specifically and forward their network traffic through the proxy server Netch is an open source game network accelerator. Unlike SSTap, which needs to add rules to function as a blacklist proxy, Netch is more similar to SocksCap64, which can scan the game directory to get their process names specifically and forward their network traffic through the proxy server
@@ -36,7 +37,7 @@ Currently supports the following protocols
As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an NATTypeTester to test out what your NAT type is. When using SSTap to speed up some P2P gaming connections or the game is required for that kind of open NAT type, you may experience some bad situations such as unable to join the game As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an NATTypeTester to test out what your NAT type is. When using SSTap to speed up some P2P gaming connections or the game is required for that kind of open NAT type, you may experience some bad situations such as unable to join the game
## Sponsor ## Sponsor
<a href="https://www.jetbrains.com/?from=Netch"><img src="images/jetbrains-variant-4.svg" alt="JetBrains" width="200"/></a> <a href="https://www.jetbrains.com/?from=Netch"><img src="jetbrains.svg" alt="JetBrains" width="200"/></a>
- [RabbitHosts](https://rabbithosts.com/cart.php) - [RabbitHosts](https://rabbithosts.com/cart.php)
- [ManSora](https://www.mansora.co/cart.php) - [ManSora](https://www.mansora.co/cart.php)
@@ -46,7 +47,7 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
- XMR *48ju3ELNZEa6wwPBMexCJ9G218BGY2XwhH6B6bmkFuJ3QgM4hPw2Pra35jPtuBZSc7SLNWeBpiWJZWjQeMAiLnTx2tH2Efx* - XMR *48ju3ELNZEa6wwPBMexCJ9G218BGY2XwhH6B6bmkFuJ3QgM4hPw2Pra35jPtuBZSc7SLNWeBpiWJZWjQeMAiLnTx2tH2Efx*
## Screenshots ## Screenshots
![](images/screenshots/main.png) ![](screenshots/main.png)
## Requirements ## Requirements
- [.NET 5](https://dotnet.microsoft.com/download/dotnet/5.0/runtime) - [.NET 5](https://dotnet.microsoft.com/download/dotnet/5.0/runtime)
@@ -56,6 +57,7 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
- [aiodns](https://github.com/aiocloud/aiodns) - [aiodns](https://github.com/aiocloud/aiodns)
- [tun2socks](https://github.com/aiocloud/tun2socks) - [tun2socks](https://github.com/aiocloud/tun2socks)
- [Redirector](https://github.com/aiocloud/Redirector) - [Redirector](https://github.com/aiocloud/Redirector)
- [RouteHelper](https://github.com/aiocloud/RouteHelper)
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester) - [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
- [NetFilter SDK](https://netfiltersdk.com) - [NetFilter SDK](https://netfiltersdk.com)
- [pcap2socks](https://github.com/zhxie/pcap2socks) - [pcap2socks](https://github.com/zhxie/pcap2socks)

View File

@@ -12,13 +12,14 @@
游戏加速工具 游戏加速工具
## TOC ## TOC
- [Netch](#Netch) - [Netch](#netch)
- [TOC](#TOC) - [TOC](#toc)
- [简介](#简介) - [简介](#简介)
- [赞助商](#赞助商) - [赞助商](#赞助商)
- [捐赠](#捐赠) - [捐赠](#捐赠)
- [依赖](#依赖) - [依赖](#依赖)
- [语言支持](#语言支持) - [语言支持](#语言支持)
- [引用](#引用)
## 简介 ## 简介
Netch 是一款 Windows 平台的开源游戏加速工具Netch 可以实现类似 SocksCap64 那样的进程代理,也可以实现 SSTap 那样的全局 TUN/TAP 代理,和 Shadowsocks-Windows 那样的本地 Socks5HTTP 和系统代理 Netch 是一款 Windows 平台的开源游戏加速工具Netch 可以实现类似 SocksCap64 那样的进程代理,也可以实现 SSTap 那样的全局 TUN/TAP 代理,和 Shadowsocks-Windows 那样的本地 Socks5HTTP 和系统代理
@@ -34,7 +35,7 @@ Netch 是一款 Windows 平台的开源游戏加速工具Netch 可以实现
与此同时 Netch 避免了 SSTap 的 NAT 问题 ,检查 NAT 类型即可知道是否有 NAT 问题。使用 SSTap 加速部分 P2P 联机,对 NAT 类型有要求的游戏时,可能会因为 NAT 类型严格遇到无法加入联机,或者其他影响游戏体验的情况 与此同时 Netch 避免了 SSTap 的 NAT 问题 ,检查 NAT 类型即可知道是否有 NAT 问题。使用 SSTap 加速部分 P2P 联机,对 NAT 类型有要求的游戏时,可能会因为 NAT 类型严格遇到无法加入联机,或者其他影响游戏体验的情况
## 赞助商 ## 赞助商
<a href="https://www.jetbrains.com/?from=Netch"><img src="images/jetbrains-variant-4.svg" alt="JetBrains" width="200"/></a> <a href="https://www.jetbrains.com/?from=Netch"><img src="jetbrains.svg" alt="JetBrains" width="200"/></a>
- [RabbitHosts](https://rabbithosts.com/cart.php) - [RabbitHosts](https://rabbithosts.com/cart.php)
- [ManSora](https://www.mansora.co/cart.php) - [ManSora](https://www.mansora.co/cart.php)
@@ -56,6 +57,7 @@ Netch 内置 en-US 和 zh-CN外置 zh-TW 等,默认根据系统语言选择
- [aiodns](https://github.com/aiocloud/aiodns) - [aiodns](https://github.com/aiocloud/aiodns)
- [tun2socks](https://github.com/aiocloud/tun2socks) - [tun2socks](https://github.com/aiocloud/tun2socks)
- [Redirector](https://github.com/aiocloud/Redirector) - [Redirector](https://github.com/aiocloud/Redirector)
- [RouteHelper](https://github.com/aiocloud/RouteHelper)
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester) - [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
- [NetFilter SDK](https://netfiltersdk.com) - [NetFilter SDK](https://netfiltersdk.com)
- [pcap2socks](https://github.com/zhxie/pcap2socks) - [pcap2socks](https://github.com/zhxie/pcap2socks)

View File

@@ -1,44 +0,0 @@
using System;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Netch.Utils;
namespace UnitTest
{
[TestClass]
public class Function : TestBase
{
[TestMethod]
public void LoadLanguage()
{
void TestLoad(string t)
{
Console.WriteLine($"Load: {t}");
i18N.Load(t);
Console.WriteLine($"Result: {i18N.LangCode}\n");
}
Directory.CreateDirectory("logging");
TestLoad("System");
TestLoad("en-US");
TestLoad("zh-CN");
TestLoad("zh-HK");
TestLoad("zh");
TestLoad("HND123&*$_-^$@SAUI");
TestLoad("");
TestLoad("-");
}
[TestMethod]
public void TestMaskToCidr()
{
Assert.AreEqual(Utils.SubnetToCidr("0.0.0.0"), 0);
Assert.AreEqual(Utils.SubnetToCidr("248.0.0.0"), 5);
Assert.AreEqual(Utils.SubnetToCidr("255.0.0.0"), 8);
Assert.AreEqual(Utils.SubnetToCidr("255.255.0.0"), 16);
Assert.AreEqual(Utils.SubnetToCidr("255.255.248.0"), 21);
Assert.AreEqual(Utils.SubnetToCidr("255.255.255.0"), 24);
Assert.AreEqual(Utils.SubnetToCidr("255.255.255.255"), 32);
}
}
}

Some files were not shown because too many files have changed in this diff Show More