Compare commits

..

413 Commits
1.7.2 ... 1.8.5

Author SHA1 Message Date
ChsBuffer
63f51a481c Bump version to 1.8.5 2021-05-28 23:39:55 +08:00
Connection Refused
e89c742f3f Add aiodns 2021-05-28 23:31:54 +08:00
ChsBuffer
458c6047af Update cloak.ps1 2021-05-28 23:29:13 +08:00
ChsBuffer
561def7fe1 Fix a typo caused China DNS not be bypassed
close #649
2021-05-28 23:28:34 +08:00
ChsBuffer
9e68fb12fb Update DNSUtils.Lookup() timeout 2021-05-28 23:24:47 +08:00
Connection Refused
d7360b3688 Update dependabot.yml 2021-05-28 23:14:11 +08:00
Connection Refused
7844c183e7 Update download.ps1 2021-05-28 23:10:56 +08:00
Connection Refused
8325bd1fe3 Update README.md 2021-05-28 23:06:35 +08:00
ChsBuffer
0a59d6aa3f Update Text
Update zh-CN
2021-05-28 22:20:19 +08:00
ChsBuffer
7fa05e7dad Update i18N
Update SettingForm AioDNSListenPortTextBox
2021-05-28 21:20:24 +08:00
ChsBuffer
b948040f9d Refactor: Replace -console argument with Show/Hide Console MenuItem 2021-05-28 21:09:23 +08:00
ChsBuffer
0c76198bd4 Update AioDNS default listen port 2021-05-28 20:59:34 +08:00
ChsBuffer
d917e5a8fa Remove AioDNS.RulePath setting
Add AioDNS.ListenPort setting
Update General setting layout
2021-05-28 20:59:15 +08:00
ChsBuffer
015e4ada94 Fix: Disable Task StopIfGoingOnBatteries
close #651
2021-05-28 15:57:15 +08:00
ChsBuffer
86b1741dd0 Revert NatTest Monitor lock 2021-05-28 14:53:27 +08:00
ChsBuffer
4af18025a7 Refactor Interops Debug log 2021-05-27 22:34:30 +08:00
ChsBuffer
3678c98fec Fix AioDNS rule config 2021-05-27 22:34:29 +08:00
ChsBuffer
9f809b4d27 Refactor: Move Updater namespace to Netch.Services 2021-05-27 22:34:29 +08:00
ChsBuffer
e3a3396d18 Refactor Started Ping 2021-05-27 22:34:28 +08:00
Connection Refused
43c19c6698 Update README.md 2021-05-25 12:35:51 +08:00
Connection Refused
9ee2a2a31a Merge pull request #650 from NetchX/dependabot/nuget/Microsoft.Diagnostics.Tracing.TraceEvent-2.0.69
Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.68 to 2.0.69
2021-05-25 12:28:04 +08:00
dependabot[bot]
489c3fc39d Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.68 to 2.0.69
Bumps [Microsoft.Diagnostics.Tracing.TraceEvent](https://github.com/Microsoft/perfview) from 2.0.68 to 2.0.69.
- [Release notes](https://github.com/Microsoft/perfview/releases)
- [Commits](https://github.com/Microsoft/perfview/compare/P2.0.68...P2.0.69)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 23:06:14 +00:00
ChsBuffer
657266df47 Update README.md 2021-05-24 16:21:12 +08:00
ChsBuffer
82ed5189c8 Refactor: Asynchronous and Lock 2021-05-17 16:25:58 +08:00
Bruce Wayne
ebe2978724 Update sha256.ps1 2021-05-14 10:16:11 +08:00
ChsBuffer
764d42efe2 Bump version to 1.8.4 2021-05-11 22:03:11 +08:00
ChsBuffer
8b81df03c4 Update TUNController.cs 2021-05-11 22:02:45 +08:00
ChsBuffer
4cc5998440 Fix suffixed version newer than release version 2021-05-11 17:17:51 +08:00
ChsBuffer
2051dd1bfe Update Nuget Packages 2021-05-10 10:08:45 +08:00
ChsBuffer
b167674d37 Update NetRoute.FillTemplate 2021-05-10 10:07:34 +08:00
ChsBuffer
74caeeaf42 Refactor TUNController 2021-05-09 15:31:43 +08:00
ChsBuffer
60dd3c8965 Refactor: Rearrange MainForm 2021-05-07 15:34:37 +08:00
ChsBuffer
ee2d35cb5d Refactor: ModeHelper, Mode.Type, Netch.Enums.ModeType 2021-05-06 23:43:13 +08:00
ChsBuffer
6f6ff85549 Refactor Guard Thread safety 2021-05-04 10:23:53 +08:00
ChsBuffer
9a8c4d6093 Fix: CloseLogFile() Thread safety 2021-05-04 10:17:33 +08:00
ChsBuffer
00268d67fa TUNController: check Interop Init() return value.
when false, throws MessageException
2021-05-04 00:24:09 +08:00
Connection Refused
b1f89c177d Update README.md 2021-05-01 11:53:07 +08:00
ChsBuffer
4a543dcf1a Refactor: Extract GetNetworkInterface By InterfaceIndex
close #630
2021-04-30 18:45:51 +08:00
ChsBuffer
5b5262e03e Update code style 2021-04-30 17:20:29 +08:00
ChsBuffer
60f0637b03 Refactor: MainForm AddServerMenuStrip get IServerUtil from Tag 2021-04-30 17:02:34 +08:00
ChsBuffer
460d295a66 Refactor TryReleaseTcpPort Process.MainModule.FileName null handling 2021-04-30 17:01:11 +08:00
ChsBuffer
ccd46144ab Refactor: save configuration 2021-04-30 15:48:43 +08:00
ChsBuffer
84e481f704 fix typo 2021-04-30 15:45:12 +08:00
ChsBuffer
fb64951003 Refactor: name, namespace 2021-04-30 15:24:37 +08:00
Connection Refused
258880ef95 Update README.md 2021-04-27 08:56:05 +08:00
Connection Refused
2bda0bdf8e Update issue templates 2021-04-27 08:47:18 +08:00
Connection Refused
bc0e5d0dcf Rename scripts 2021-04-27 08:43:35 +08:00
Connection Refused
4e4af89fbe Remove README.zh-CN.md 2021-04-27 08:43:31 +08:00
Connection Refused
1e9ff83aa2 Update README.md 2021-04-27 08:40:22 +08:00
Connection Refused
a4d8619944 Update README.md 2021-04-27 08:38:39 +08:00
Connection Refused
0bb54abe6c Update README.md 2021-04-27 08:03:51 +08:00
Connection Refused
0ad18ee566 Update README.md 2021-04-27 08:03:26 +08:00
Connection Refused
80460c0a21 Update README.md 2021-04-27 08:02:14 +08:00
Connection Refused
098680482e Merge pull request #628 from NetchX/dependabot/nuget/Microsoft.Diagnostics.Tracing.TraceEvent-2.0.68
Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.67 to 2.0.68
2021-04-27 07:24:17 +08:00
dependabot[bot]
16d7f53ee3 Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.67 to 2.0.68
Bumps [Microsoft.Diagnostics.Tracing.TraceEvent](https://github.com/Microsoft/perfview) from 2.0.67 to 2.0.68.
- [Release notes](https://github.com/Microsoft/perfview/releases)
- [Commits](https://github.com/Microsoft/perfview/compare/P2.0.67...P2.0.68)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-26 23:06:25 +00:00
Connection Refused
ed946c44a2 Merge pull request #627 from NetchX/dependabot/nuget/Microsoft.Diagnostics.Tracing.TraceEvent-2.0.67
Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.66 to 2.0.67
2021-04-24 01:38:08 +08:00
dependabot[bot]
62c28ccab2 Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.66 to 2.0.67
Bumps [Microsoft.Diagnostics.Tracing.TraceEvent](https://github.com/Microsoft/perfview) from 2.0.66 to 2.0.67.
- [Release notes](https://github.com/Microsoft/perfview/releases)
- [Commits](https://github.com/Microsoft/perfview/compare/P2.0.66...P2.0.67)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-22 23:12:13 +00:00
ChsBuffer
a2326389db Fix: Use WMI to set dummy Dns on the tun interface to ensure DNS is hijacked 2021-04-21 18:25:37 +08:00
Connection Refused
b0086cc854 Add ethereum donate address 2021-04-21 17:33:25 +08:00
Connection Refused
d2548d2893 Add ethereum donate address 2021-04-21 17:32:50 +08:00
Connection Refused
101d8c5a25 Update telegram links 2021-04-21 17:27:33 +08:00
Bruce Wayne
1b36b707f6 Update issue forms 2021-04-21 11:20:03 +08:00
Bruce Wayne
a94bf0d53d Update issue forms 2021-04-21 11:17:24 +08:00
Bruce Wayne
32a9261041 Update issue forms 2021-04-21 09:43:29 +08:00
Bruce Wayne
2b0530d9b0 Update issue forms 2021-04-21 09:23:52 +08:00
Bruce Wayne
2d85e78b77 Drop old issue template 2021-04-21 09:22:12 +08:00
Connection Refused
b8b4dbfb0a Update release.yml 2021-04-18 15:53:29 +08:00
Connection Refused
025eda8286 Update README.md 2021-04-18 15:53:05 +08:00
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
ChsBuffer
5522245ce0 bump version to 1.8.3-Beta5 2021-03-28 02:47:19 +08:00
ChsBuffer
f518fd6867 Update binaries(Fix DNS) 2021-03-28 02:23:01 +08:00
ChsBuffer
e0120e7de0 Update SettingForm 2021-03-28 02:21:44 +08:00
ChsBuffer
3565251b4d Update Redirector
extract RedirectorConfig
move BypassIPs to Setting.TUNTAP
2021-03-28 02:13:03 +08:00
ChsBuffer
4a50ebd421 Update zh-cn 2021-03-28 02:13:03 +08:00
Connection Refused
4e03793ceb Update submodules 2021-03-28 02:05:24 +08:00
ChsBuffer
23399b872d Remove TUN HijackDNS value check 2021-03-28 00:56:59 +08:00
ChsBuffer
b553ddbb71 Refactor: Create Netch.Interops namespace 2021-03-28 00:54:04 +08:00
ChsBuffer
090e487733 Move MessageException Namespace and Optimize import 2021-03-28 00:51:42 +08:00
ChsBuffer
cada4c997e Update Release workflow 2021-03-28 00:13:49 +08:00
ChsBuffer
8746125dda Create Publish.ps1 2021-03-28 00:01:59 +08:00
ChsBuffer
d09b5adc33 Drop proxy client routing 2021-03-27 23:44:25 +08:00
ChsBuffer
54c1fb5578 remove unused aiodns protocol setting 2021-03-27 23:20:56 +08:00
ChsBuffer
f07413c882 Fix LogForm RouteForm Scale 2021-03-27 23:15:25 +08:00
ChsBuffer
5b2b6c9f96 Update DNSController and TUNController 2021-03-27 23:09:33 +08:00
ChsBuffer
4c4ad72d1d Update Setting 2021-03-27 22:55:18 +08:00
Connection Refused
830f3b3b60 Update modes 2021-03-27 22:33:20 +08:00
Connection Refused
777657e810 Update modes 2021-03-27 22:27:58 +08:00
Connection Refused
2413aabb15 Update aiodns to v1.0.3 2021-03-27 22:16:26 +08:00
Connection Refused
6ccb99d1d8 Update tun2socks 2021-03-27 22:10:23 +08:00
Connection Refused
ac0266a478 Update tun2socks 2021-03-27 21:51:30 +08:00
ChsBuffer
d701a8c950 Fix Create Process Mode validation typo
Update NFController
2021-03-27 19:41:16 +08:00
ChsBuffer
934443556c extract RedirectorInterop
Update TUNController
2021-03-27 19:29:42 +08:00
ChsBuffer
a69252819c Update Readme 2021-03-27 18:36:40 +08:00
ChsBuffer
f90773aa84 Update StringExtension Split 2021-03-27 18:27:09 +08:00
ChsBuffer
246f52e54e cleanup Reference 2021-03-27 18:24:13 +08:00
ChsBuffer
a5f6b4a2c0 Fix BUILD.ps1 2021-03-27 18:09:00 +08:00
ChsBuffer
66d7cededd Fix LogForm RouteForm ScaleDimensions 2021-03-27 17:59:13 +08:00
ChsBuffer
8254482799 Remove SearchComboBox 2021-03-27 17:56:34 +08:00
ChsBuffer
b215b2caa8 Fix TUNNetmaskTextBox Visible 2021-03-27 17:45:50 +08:00
ChsBuffer
5f9dbb0994 Update BUILD.ps1, Remove CLEAN.ps1 2021-03-27 17:44:47 +08:00
ChsBuffer
3cbd5af9a3 Extract TagItem class, Update Nullable 2021-03-27 17:40:18 +08:00
ChsBuffer
2ab693facf Update TFM to net5.0-windows7 2021-03-27 16:26:18 +08:00
ChsBuffer
664b1a7e6c Update TUNController 2021-03-27 16:24:15 +08:00
Connection Refused
ad1575b3c7 Update modes 2021-03-27 16:00:35 +08:00
Connection Refused
62b78d1b1d Update submodules 2021-03-27 15:56:04 +08:00
ChsBuffer
dd3ce126e3 Update TUNController (tun2socks.bin) 2021-03-27 03:06:54 +08:00
ChsBuffer
a295cf6250 Update Append bin to PATH 2021-03-27 03:05:45 +08:00
ChsBuffer
a507df5f30 Debug Level Log 2021-03-27 03:05:32 +08:00
ChsBuffer
0a7b405f1b Revert "Update Netch.csproj"
This reverts commit 5fc7c460aa.
2021-03-26 23:40:33 +08:00
Connection Refused
c61da9b918 Update modes 2021-03-26 19:39:54 +08:00
Connection Refused
9bf3490cf9 Update TUNController 2021-03-26 19:32:57 +08:00
Connection Refused
c505e2abbb Update TUNController 2021-03-26 19:31:42 +08:00
Connection Refused
5fc7c460aa Update Netch.csproj 2021-03-26 19:31:28 +08:00
Connection Refused
c79f62334c Update aiodns.conf 2021-03-26 19:18:31 +08:00
Connection Refused
2dc4308427 Update aiodns.conf 2021-03-26 19:18:09 +08:00
Connection Refused
c3c534eb92 Update binaries 2021-03-26 19:14:14 +08:00
Connection Refused
dbef41d8a4 Update README.md 2021-03-26 18:40:32 +08:00
ChsBuffer
e3d6a62e81 Update RouteHelper usage 2021-03-26 18:35:46 +08:00
ChsBuffer
415c7705ac cleanup drop http support 2021-03-26 18:35:12 +08:00
Connection Refused
4ab844e31c Update NativeMethods 2021-03-26 18:25:08 +08:00
ChsBuffer
f4759d2f94 Drop HTTPController(Drop WebProxy, Update server with proxy etc.) 2021-03-26 18:17:58 +08:00
ChsBuffer
a080de6ca4 replace eycorsican/go-tun2socks with aiocloud/tun2socks(WinTUN) 2021-03-26 17:56:28 +08:00
Connection Refused
f8148cb730 Merge pull request #598 from NetchX/dependabot/submodules/modes-1471298
Bump modes from `72ad96d` to `1471298`
2021-03-26 17:04:27 +08:00
dependabot[bot]
b092b6a4d4 Bump modes from 72ad96d to 1471298
Bumps [modes](https://github.com/NetchX/NetchMode) from `72ad96d` to `1471298`.
- [Release notes](https://github.com/NetchX/NetchMode/releases)
- [Commits](72ad96d018...1471298210)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-26 09:04:07 +00:00
ChsBuffer
e2bcdc8840 Bump version to 1.8.3-Beta4 2021-03-26 15:00:22 +08:00
ChsBuffer
4202c8ac5a Refactor Add Guard.Keywords setter 2021-03-26 13:03:37 +08:00
ChsBuffer
db765d60f0 Fix possible null reference warning 2021-03-26 12:02:34 +08:00
ChsBuffer
28c248ea70 Fix Updater.cs import 2021-03-26 10:35:25 +08:00
ChsBuffer
f818c444a4 Refactor create tun2socks arguments and setup route table after tun2socks started 2021-03-26 10:29:51 +08:00
ChsBuffer
d260afd49b Feat: -forceUpdate Parameter 2021-03-26 10:29:50 +08:00
ChsBuffer
66bfe39674 Improve Updater stability 2021-03-26 10:29:50 +08:00
AmazingDM
95d1b039cd update binaries 2021-03-26 10:20:30 +08:00
ChsBuffer
b2a7d4fd59 upgrade nuget packages 2021-03-26 10:20:29 +08:00
ChsBuffer
ec6b9a2c18 Fix PostBuild call bat 2021-03-26 10:20:29 +08:00
ChsBuffer
dcb90ccdcd Refactor: split Global.cs 2021-03-25 12:21:42 +08:00
ChsBuffer
5da5daa112 extract Interop.nfapinet project 2021-03-24 23:12:15 +08:00
ChsBuffer
5d5ee40cd6 Migrate to HMBSbige.SingleInstance 2021-03-24 11:32:26 +08:00
ChsBuffer
32d3e97288 Update TryReleaseUsedTcpPort 2021-03-24 11:32:26 +08:00
ChsBuffer
452c5ec67c Extract LogStopwatch class 2021-03-24 11:32:25 +08:00
AmazingDM
9d2fd2cce3 Update UpdateChecker.cs 2021-03-24 10:30:10 +08:00
AmazingDM
5a3295d10c RDR Memory optimization 2021-03-23 22:28:23 +08:00
ChsBuffer
8269948288 Update GetProcessByUsedTcpPort (Fix #591) 2021-03-23 16:14:34 +08:00
ChsBuffer
8e545fc05f Remove Reload Mode MenuToolStrip 2021-03-23 13:41:43 +08:00
ChsBuffer
9a3a1e3664 Fix #589 GetProcessByUsedTcpPort multiple process 2021-03-22 22:01:03 +08:00
AmazingDM
3f4a31dac8 Update UpdateChecker.cs 2021-03-22 21:40:26 +08:00
AmazingDM
7c0088cc7f optimization 2021-03-22 21:23:11 +08:00
ChsBuffer
1a28d791b7 Merge pull request #585 from NetchX/dependabot/nuget/Vanara.PInvoke.IpHlpApi-3.3.6
Bump Vanara.PInvoke.IpHlpApi from 3.3.5 to 3.3.6
2021-03-22 11:18:42 +08:00
ChsBuffer
05df786ab6 Merge pull request #586 from NetchX/dependabot/nuget/Vanara.PInvoke.User32-3.3.6
Bump Vanara.PInvoke.User32 from 3.3.5 to 3.3.6
2021-03-22 11:18:33 +08:00
ChsBuffer
1ffbae6135 Feat: Show Release Note when confirm 2021-03-22 11:09:16 +08:00
dependabot[bot]
8ca9d6d9be Bump Vanara.PInvoke.User32 from 3.3.5 to 3.3.6
Bumps [Vanara.PInvoke.User32](https://github.com/dahall/vanara) from 3.3.5 to 3.3.6.
- [Release notes](https://github.com/dahall/vanara/releases)
- [Commits](https://github.com/dahall/vanara/compare/v3.3.5...v3.3.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-21 23:10:21 +00:00
dependabot[bot]
4f1ae20b9b Bump Vanara.PInvoke.IpHlpApi from 3.3.5 to 3.3.6
Bumps [Vanara.PInvoke.IpHlpApi](https://github.com/dahall/vanara) from 3.3.5 to 3.3.6.
- [Release notes](https://github.com/dahall/vanara/releases)
- [Commits](https://github.com/dahall/vanara/compare/v3.3.5...v3.3.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-21 23:10:16 +00:00
ChsBuffer
15a1db3b21 Feat: Backup configuration file before update 2021-03-22 01:59:49 +08:00
ChsBuffer
54243a80e7 Update SuffixVersion 2021-03-22 01:43:06 +08:00
ChsBuffer
947bf2b3ca Bump version to 1.8.3-Beta1 2021-03-21 22:53:00 +08:00
ChsBuffer
2a165c79df Start Profile, Refactor Save LastSelectedServer/Mode 2021-03-21 22:44:15 +08:00
ChsBuffer
55280df299 Update Load configuration 2021-03-21 22:00:16 +08:00
ChsBuffer
af48e7119e Auto reload modes, Lazy load mode rules 2021-03-21 04:54:33 +08:00
ChsBuffer
a1b978a22c Remove WindowsJobAPI 2021-03-21 03:38:34 +08:00
ChsBuffer
d08a9d5bfd Refactor Start Port Check Kill Process 2021-03-21 03:38:25 +08:00
ChsBuffer
c69c40750a Fix a typo 2021-03-21 01:48:44 +08:00
ChsBuffer
77376502b7 Update CI 2021-03-21 00:05:20 +08:00
ChsBuffer
fdfc3f11eb Update NFController 2021-03-20 21:38:24 +08:00
AmazingDM
0d956efac6 update binaries 2021-03-20 20:36:37 +08:00
AmazingDM
3f9709167d update NFController
optimization rdr
2021-03-20 20:35:56 +08:00
ChsBuffer
425e468f78 Revert "Update Netch.csproj to be compatible with dotnet cli"
This reverts commit 77f2b761fc.
2021-03-20 18:33:04 +08:00
AmazingDM
a485a4647c fix error set TYPE_FILTERCHILDPROC 2021-03-20 17:56:45 +08:00
ChsBuffer
0b484face4 Update Edit Process Mode Form 2021-03-20 04:33:35 +08:00
ChsBuffer
e0b5b0e49c Restore Edit Process Scan Button And Update Select Button 2021-03-20 03:41:37 +08:00
ChsBuffer
f519850ffc Trim 2021-03-20 00:50:06 +08:00
ChsBuffer
4513a68e73 Update Nuget packages
Bump MSTest.TestAdapter from 2.2.1 to 2.2.3
Bump MSTest.TestFramework from 2.2.1 to 2.2.3
2021-03-19 03:58:57 +08:00
ChsBuffer
95de42e778 Update SS/SSR Parameter 2021-03-19 03:56:54 +08:00
ChsBuffer
18168c3a4e Add Nullable.Extended.Analyzer 2021-03-19 03:50:08 +08:00
ChsBuffer
77f2b761fc Update Netch.csproj to be compatible with dotnet cli 2021-03-19 03:07:07 +08:00
ChsBuffer
9bd02ec122 Update Debug Logging 2021-03-19 03:05:57 +08:00
ChsBuffer
cfb4a5b3f6 The Debug configuration will make the build attach to the console and write the application log to standard output 2021-03-19 00:58:34 +08:00
ChsBuffer
6178045f15 Fix Import v2rayN format sharelink got exception when property type Number 2021-03-16 16:43:46 +08:00
ChsBuffer
4773de99e5 Fix typo 2021-03-16 16:41:35 +08:00
ChsBuffer
eb713db867 Refactor: generate SS/SSR start arguments 2021-03-16 15:55:46 +08:00
ChsBuffer
15f4895c0f Update UnitTest 2021-03-16 15:24:30 +08:00
ChsBuffer
afbda60dfb format NFController 2021-03-16 15:19:25 +08:00
ChsBuffer
f51229f2c8 Fix: SS/SSR password not allow empty and Update Model 2021-03-16 15:19:12 +08:00
ChsBuffer
26f9ae3958 Update Server Model value type 2021-03-15 22:38:33 +08:00
ChsBuffer
dfc680f0b7 Update .gitignore 2021-03-15 22:10:46 +08:00
ChsBuffer
5e56556534 Remove unused resources 2021-03-15 22:03:47 +08:00
ChsBuffer
33a0d9e7c2 Bump version to 1.8.2 2021-03-14 18:09:17 +08:00
ChsBuffer
939d600be1 Refactor SettingForm 2021-03-14 17:48:38 +08:00
ChsBuffer
a1e511915e Refactor: MainForm Start failed MessageBoxX level to Error 2021-03-13 02:32:04 +08:00
ChsBuffer
94796110d5 Refactor Mode Form
Process Mode Form Scan to Select
Remove UseCustomName
Mode.get_FullRule throw MessageException
2021-03-13 02:27:38 +08:00
ChsBuffer
5c3e2ab207 Refactor Updater 2021-03-13 01:13:54 +08:00
ChsBuffer
e66eb9759a Refactor LoadModes 2021-03-13 01:13:39 +08:00
ChsBuffer
b27ccfab17 Add more comments to Updater
Updater Keeps disabled file
LazyLoad Global.Mutex
Fix AfterUpdate Release Global.Mutex
2021-03-13 00:26:21 +08:00
ChsBuffer
87b3867095 Feature: Load mode ignores directories with "disabled" files in the directory 2021-03-12 23:41:36 +08:00
ChsBuffer
3d1538264a Update docs 2021-03-12 15:46:39 +08:00
AmazingDM
0bffbbfb62 Merge pull request #564 from NetchX/dependabot/submodules/modes-42375ef
Bump modes from `7bcbf86` to `42375ef`
2021-03-12 11:10:21 +08:00
dependabot[bot]
6ccbcae31f Bump modes from 7bcbf86 to 42375ef
Bumps [modes](https://github.com/NetchX/NetchMode) from `7bcbf86` to `42375ef`.
- [Release notes](https://github.com/NetchX/NetchMode/releases)
- [Commits](7bcbf86f5c...42375ef724)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-11 23:05:46 +00:00
ChsBuffer
5a9d6e145d Cut SS DLL 2021-03-11 13:12:26 +08:00
ChsBuffer
1b7eb6f6de Merge pull request #561 from NetchX/dependabot/submodules/modes-7bcbf86
Bump modes from `dd436b3` to `7bcbf86`
2021-03-11 13:07:57 +08:00
dependabot[bot]
62bfa25870 Bump modes from dd436b3 to 7bcbf86
Bumps [modes](https://github.com/NetchX/NetchMode) from `dd436b3` to `7bcbf86`.
- [Release notes](https://github.com/NetchX/NetchMode/releases)
- [Commits](dd436b3652...7bcbf86f5c)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-11 04:29:53 +00:00
ChsBuffer
a1d481ba05 Update dependabot check submodule update interval 2021-03-11 12:21:35 +08:00
ChsBuffer
39abcb7d79 Merge pull request #555 from NetchX/dependabot/nuget/WindowsProxy-5.0.3
Bump WindowsProxy from 5.0.0 to 5.0.3
2021-03-09 07:09:05 +08:00
dependabot[bot]
7c1df3786e Bump WindowsProxy from 5.0.0 to 5.0.3
Bumps [WindowsProxy](https://github.com/HMBSbige/WindowsProxy) from 5.0.0 to 5.0.3.
- [Release notes](https://github.com/HMBSbige/WindowsProxy/releases)
- [Commits](https://github.com/HMBSbige/WindowsProxy/compare/5.0.0...5.0.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-08 23:05:14 +00:00
AmazingDM
fe11ee56ba update NF driver to 1.6.0.7
update RDR ChildProcessHandle
2021-03-08 12:06:24 +08:00
ChsBuffer
4f38de4ee9 remove HTTPController.Stop try catch set state 2021-03-08 10:55:23 +08:00
ChsBuffer
1aa32eaf3a HTTPController.Stop check state validity 2021-03-08 09:07:50 +08:00
AmazingDM
4b3d6fb3bf DNS , ICMP Redirector
Child process handle
2021-03-06 14:04:50 +08:00
ChsBuffer
12559d8192 Fix MainController.Stop() didn't catch multiple exceptions 2021-03-06 05:05:21 +08:00
ChsBuffer
bd71452206 MainController.StopAsync() Exception handling 2021-03-06 04:49:11 +08:00
ChsBuffer
10ba299f4d Refactor Updater exception and release UpdaterChecker Event's EventHandler
Fix didn't Remove broken update file
2021-03-06 02:56:41 +08:00
ChsBuffer
1ff9d1ec9d Maybe fix #545 2021-03-05 22:13:27 +08:00
ChsBuffer
9cbb88c886 Open Opened Netch Window using win32 apis 2021-03-05 21:19:10 +08:00
ChsBuffer
7e65ae0b6b Open Opened Netch Window using win32 apis 2021-03-05 18:01:30 +08:00
ChsBuffer
41491f8c20 Cut OnlyInstance 2021-03-05 16:07:21 +08:00
ChsBuffer
84b412bc8c bump version to 1.8.1 2021-03-05 15:15:03 +08:00
ChsBuffer
7fef3dfe5c Update pcap2socks modes 2021-03-05 15:14:11 +08:00
ChsBuffer
c139a82bdf Fix Remove invalid profile error
Exit when Load Configuration error
2021-03-05 14:50:25 +08:00
ChsBuffer
97f6d601fb Fix pcap2socks no --destination argument, Update Guard 2021-03-05 01:02:59 +08:00
ChsBuffer
1ea0bb4096 ignore JsonSerializer.Deserialize return value possible null 2021-03-05 00:22:57 +08:00
ChsBuffer
7265bd2922 Update pcap2socks doc Quote 2021-03-04 23:51:24 +08:00
ChsBuffer
f316e13ada Open log file only once when parsing sharedlinks throws many exceptions 2021-03-04 23:38:30 +08:00
ChsBuffer
370794646d Revert "Update CI"
This reverts commit 50678fba42.
2021-03-04 22:00:46 +08:00
ChsBuffer
677ac07d9a Bump version to 1.8.0 2021-03-04 21:51:06 +08:00
ChsBuffer
cba6e6b668 update submodules 2021-03-04 21:50:26 +08:00
ChsBuffer
64260b18cc Create LogForm and use on PcapController 2021-03-04 21:25:34 +08:00
ChsBuffer
74e1635e26 Update Guard 2021-03-04 21:00:12 +08:00
ChsBuffer
b6e4e5effa throw right exception when Deserialize v2rayN ShareLink 2021-03-04 15:37:12 +08:00
ChsBuffer
c1644ec52f Create PcapController 2021-03-04 05:16:21 +08:00
ChsBuffer
e5a968f581 Update Guard 2021-03-04 04:57:05 +08:00
ChsBuffer
dc7c537eef SettingForm bind STUN and Language Settings Control 2021-03-04 00:46:49 +08:00
ChsBuffer
1fc211acde Global.Settings.ProcessProxyProtocol 2021-03-03 23:05:04 +08:00
ChsBuffer
0ce8bbf712 Fix ProxyDNSCheckBox overflow 2021-03-03 22:06:25 +08:00
ChsBuffer
1003521d01 Proxy AioDNS OtherDNS when UseCustomDNS disabled, Proxy DNS in Proxy Rule IPs Mode enabled 2021-03-03 22:01:44 +08:00
ChsBuffer
026eb75eb1 Revert Bind ProxyDNSCheckBox.Enabled to UseCustomDNSCheckBox.Checked 2021-03-03 21:59:22 +08:00
ChsBuffer
e42b98cf03 Change ProxyDNSCheckBox.Text to "Update DNS in Proxy Rule IPs Mode" ,bind Enabled to UseCustomDNSCheckBox.Checked 2021-03-03 20:11:49 +08:00
ChsBuffer
93eeaf8c75 Disable Proxy Rule IPs mode Nat test 2021-03-03 20:00:54 +08:00
ChsBuffer
e99772ad11 Rename DNS to DnsUtils 2021-03-03 19:49:32 +08:00
ChsBuffer
0714a7bc12 Refactor Get NetworkInterfaces 2021-03-03 19:37:04 +08:00
ChsBuffer
f3515974f8 Update dependencies 2021-03-02 18:05:28 +08:00
ChsBuffer
50678fba42 Update CI 2021-03-02 17:56:24 +08:00
ChsBuffer
29532e9353 Update UnitTest 2021-03-02 17:30:47 +08:00
ChsBuffer
66e219f8a6 Update dependabot.yml 2021-03-02 15:53:12 +08:00
ChsBuffer
8789b04953 Update zh-CN 2021-03-01 23:54:30 +08:00
ChsBuffer
3fd8100aa5 Remove Win32Native.cs 2021-03-01 23:14:38 +08:00
ChsBuffer
e03fe9fec9 throw MessageException when Guard.MainFile not found. 2021-03-01 23:14:12 +08:00
ChsBuffer
eab0797fb2 Fix Save configuration lost Server derived class's properties 2021-03-01 22:42:28 +08:00
ChsBuffer
046079639e Update PAC Http Server 2021-03-01 22:30:22 +08:00
ChsBuffer
a5147e147e Fix #529 Trojan start failed 2021-03-01 21:07:34 +08:00
ChsBuffer
f9503d61d3 Update HTTPController 2021-03-01 21:07:14 +08:00
ChsBuffer
389c385d18 Update WindowsProxy usage
Close #530
2021-03-01 20:55:14 +08:00
ChsBuffer
3f6744205a Update Updater 2021-03-01 20:25:09 +08:00
ChsBuffer
5e168d9e50 lazy initialization SupportFakeDns 2021-03-01 19:28:14 +08:00
ChsBuffer
ad660fb598 lazy initialization MainForm 2021-03-01 17:13:07 +08:00
ChsBuffer
dfe5a4528b Merge pull request #526 from NetchX/JSON
Migrate from Newtonsoft.Json to System.Text.Json
2021-03-01 17:12:31 +08:00
ChsBuffer
5225a98581 Migrate from Newtonsoft.Json to System.Text.Json 2021-03-01 16:39:11 +08:00
ChsBuffer
74aa072d9b Models fields to properties 2021-03-01 15:38:00 +08:00
ChsBuffer
dd5dee02c5 Enable Nullable 2021-02-28 22:17:12 +08:00
ChsBuffer
6d4e12a6f2 make Copy To Output or Publish Directory directories invisible in project 2021-02-28 20:57:08 +08:00
ChsBuffer
790abce3c8 Fix #528 socks5 only mode start failed 2021-02-28 20:51:43 +08:00
ChsBuffer
e0ca3a5ee4 Refactor Server.Type 2021-02-26 14:16:41 +08:00
ChsBuffer
fde71e922f Fix: Remove in directory firewall rules ignore application name case
Fix: Windows Firewall Notification
Refactor: create firewall rules by searching directory exe files
2021-02-26 13:52:29 +08:00
ChsBuffer
140912bd2f Remove Netch Firewall Rules will Remove rules that ApplicationName Start with Netch Directory. 2021-02-26 13:42:32 +08:00
ChsBuffer
677be9ba53 Fix OnlyInstance Send Command Client bind address 2021-02-26 13:35:37 +08:00
ChsBuffer
146f2013ee Control ModifierKey to Test Selected Server 2021-02-26 13:29:52 +08:00
ChsBuffer
7ad89e7803 Update UnitTest 2021-02-26 00:20:59 +08:00
ChsBuffer
e9246bb300 Update UnitTest 2021-02-26 00:17:12 +08:00
ChsBuffer
2e81e41ae3 Update Test project 2021-02-26 00:03:57 +08:00
ChsBuffer
c3e2314bcd Refactor Load Language 2021-02-26 00:03:51 +08:00
ChsBuffer
bcbb7928c3 Update china_site_list & default.acl 2021-02-24 01:53:26 +08:00
ChsBuffer
7ea525a8ea Refactor Redirect Output 2021-02-23 18:32:55 +08:00
ChsBuffer
758a4ca57e Fix NTT parse stderr
Refactor Split string
Refactor GetReservedPortRange
2021-02-23 17:12:19 +08:00
ChsBuffer
f752c883ca Revert "Attach Console MenuItem"
This reverts commit 244f32e9f4.
2021-02-23 15:23:33 +08:00
ChsBuffer
ba646e43e3 Update Edit Mode Form ctor check mode 2021-02-23 14:08:54 +08:00
ChsBuffer
210bafb33f Fix Parse VLESS Sharelink 2021-02-23 14:08:53 +08:00
Connection Refused
67fb8f449b Merge pull request #521 from NetchX/dependabot/nuget/Microsoft.Diagnostics.Tracing.TraceEvent-2.0.66
Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.65 to 2.0.66
2021-02-23 07:09:25 +08:00
dependabot[bot]
fa57761013 Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.65 to 2.0.66
Bumps [Microsoft.Diagnostics.Tracing.TraceEvent](https://github.com/Microsoft/perfview) from 2.0.65 to 2.0.66.
- [Release notes](https://github.com/Microsoft/perfview/releases)
- [Commits](https://github.com/Microsoft/perfview/compare/P2.0.65...P2.0.66)

Signed-off-by: dependabot[bot] <support@github.com>
2021-02-22 23:05:06 +00:00
ChsBuffer
96dd2e7bf2 Change V2rayConfig.AllowInsecure default to false 2021-02-22 23:50:46 +08:00
ChsBuffer
890ebeb592 Remove Form resx 2021-02-22 17:11:01 +08:00
ChsBuffer
eb88be81e2 Fix ACL FullPath argument 2021-02-22 16:59:33 +08:00
ChsBuffer
cb18816e64 Create Edit Route Table Rule 2021-02-22 16:56:47 +08:00
ChsBuffer
244f32e9f4 Attach Console MenuItem 2021-02-22 00:28:20 +08:00
ChsBuffer
6de9d73699 bump version to 1.7.6 2021-02-20 21:04:12 +08:00
ChsBuffer
a2d1d85e69 fix typo 2021-02-20 20:53:48 +08:00
ChsBuffer
750d3d6dc6 bump version to 1.7.5 2021-02-20 19:04:48 +08:00
ChsBuffer
17f88abcb2 Update VShareLink Utils 2021-02-20 19:00:42 +08:00
ChsBuffer
ac0800ec56 Reformat 2021-02-20 18:15:16 +08:00
ChsBuffer
021f940957 Update .editorconfig 2021-02-20 18:14:57 +08:00
ChsBuffer
192a00b1a9 Fix StartedKeywords StoppedKeywords values 2021-02-20 16:25:08 +08:00
ChsBuffer
212aaf8a8f Update ACL to "data" 2021-02-20 16:06:00 +08:00
ChsBuffer
aa627cbaf9 Reformat csproj
Disable Release Variants debug symbols
2021-02-20 15:29:48 +08:00
ChsBuffer
af3fa23862 Compatible with dotnet core 2021-02-20 14:46:05 +08:00
ChsBuffer
1590712c65 Fix Update Profiles format 2021-02-20 14:13:10 +08:00
ChsBuffer
774980e41f Rename Init Methods 2021-02-19 23:46:14 +08:00
ChsBuffer
d6189e2ea6 ProfileTableColumnCount value check 2021-02-19 22:53:27 +08:00
ChsBuffer
99ad0b8920 Refactor Profile
Feat Multiple Rows ProfileTable
Cut Remove Profile Confirm
2021-02-19 22:36:02 +08:00
ChsBuffer
446fcc17da Disable ServerForm Designer 2021-02-19 17:48:01 +08:00
ChsBuffer
7e9875a096 Rename NetchLib to SearchComboBox 2021-02-19 17:33:07 +08:00
ChsBuffer
0e89c8726b Add dependabot 2021-02-19 17:01:27 +08:00
ChsBuffer
197c78ed70 Update docs 2021-02-19 01:32:21 +08:00
ChsBuffer
ae8b6ad41d Refactor Bandwidth.Compute() 2021-02-19 01:18:07 +08:00
ChsBuffer
604001e461 Rename StringEx.cs to StringExtension.cs 2021-02-19 00:01:56 +08:00
ChsBuffer
c29c55bd40 Refactor StartFailed 2021-02-18 23:58:39 +08:00
ChsBuffer
0eb60d0c90 Netch.Global.NetchExecutable 2021-02-18 19:30:31 +08:00
ChsBuffer
710dd646b9 Move V2rayUtils 2021-02-16 22:37:33 +08:00
ChsBuffer
182937ab69 Fix QUIC 2021-02-16 22:34:13 +08:00
ChsBuffer
07ec5fb84a Remove VMess.QUIC 2021-02-16 22:00:27 +08:00
ChsBuffer
8f8fa159c7 Feat #517 new VMess/VLESS ShareLink format get and parse 2021-02-16 21:03:50 +08:00
ChsBuffer
eac456b3a8 Fix TLSSecureType "none" value 2021-02-16 18:53:07 +08:00
ChsBuffer
04afea7d1c update HTTPController 2021-02-16 18:20:32 +08:00
ChsBuffer
c4a1af2b7b Fix #516 firewall rule profiles 2021-02-16 09:53:17 +08:00
ChsBuffer
649ce3d3d0 Remove NETCONLib COM 2021-02-14 22:35:57 +08:00
ChsBuffer
115e418879 Add 7za.exe 2021-02-14 22:32:45 +08:00
ChsBuffer
400b69d70b Fix Typo 2021-02-14 22:18:49 +08:00
ChsBuffer
3771d39fb0 RDR Bypass Netch Directory 2021-02-14 22:16:42 +08:00
ChsBuffer
fd410ea388 Cut TAP Network Sharing 2021-02-14 21:40:04 +08:00
ChsBuffer
dacebc0eaa TryCatch CleanOld File.Delete 2021-02-14 17:04:27 +08:00
ChsBuffer
3ae8467508 Refactor Mode, Save mode into mode\\Custom\\ 2021-02-14 13:49:13 +08:00
ChsBuffer
faa3cf3770 Move Updater into Main Program 2021-02-14 13:19:58 +08:00
ChsBuffer
f728759bb2 Remove Add subscribe confirm msg 2021-02-14 11:10:33 +08:00
ChsBuffer
01889cd660 Vanara.PInvoke.IpHlpApi 2021-02-14 10:58:51 +08:00
ChsBuffer
a853b9831f Bump version to 1.7.4 2021-02-13 14:42:41 +08:00
ChsBuffer
3d37b042f6 Feat: Check if the bin folder exists 2021-02-13 14:38:23 +08:00
ChsBuffer
1f9607ba1e Remove localization folders 2021-02-13 14:24:51 +08:00
ChsBuffer
8443772b75 Add RemoveNetchFirewallRules MenuItem 2021-02-13 14:13:49 +08:00
ChsBuffer
aaad1697b3 Replace NetFwTypeLib COMReference with WindowsFirewallHelper 2021-02-13 14:11:58 +08:00
ChsBuffer
35688003d5 Replace TaskScheduler COMReference with PackageReference 2021-02-13 13:20:11 +08:00
ChsBuffer
19afbf1993 Update stun.txt 2021-02-13 12:45:53 +08:00
ChsBuffer
3cd0b59bf6 Upgrade packages 2021-02-13 12:40:35 +08:00
ChsBuffer
b26aecf7e8 fix ICMPing async warning 2021-02-13 12:39:21 +08:00
ChsBuffer
18f71d3862 Update PostBuild.bat 2021-02-13 12:38:36 +08:00
ChsBuffer
0bd0d06867 Replace v2ray-core with Xray-core 2021-02-13 08:40:47 +08:00
ChsBuffer
96001500f0 Guard.InitInstance() to virtual method 2021-02-12 07:56:42 +08:00
ChsBuffer
11ab1b89af Refactor IServerController 2021-02-12 00:34:17 +08:00
AmazingDM
811e2828fb update submodule 2021-02-09 17:52:29 +08:00
AmazingDM
68a2e4b705 Update UpdateChecker.cs 2021-02-08 11:41:45 +08:00
ChsBuffer
8e83359e39 Bump version to 1.7.3 2021-01-26 21:57:24 +08:00
ChsBuffer
d2b6d182ff Remove Delay Test "Test done" Notification 2021-01-26 21:51:47 +08:00
ChsBuffer
019044c275 Refactor:
Move NatTest to MainForm
  Move call NetTraffic() NatTest() to ControlButton_Click()
2021-01-26 21:50:33 +08:00
ChsBuffer
df48eb3067 Disable Update Servers with proxy when started 2021-01-26 21:43:33 +08:00
ChsBuffer
6bfcae453f Fix #498 , again 2021-01-26 21:36:23 +08:00
ChsBuffer
7d55af2101 Fix speed test caused lost status port info 2021-01-26 00:59:46 +08:00
ChsBuffer
9172ede7c2 Refactor DrawItem 2021-01-18 05:51:38 +08:00
ChsBuffer
fb8aa548ac Cut: Exclude Server.Delay property from serialization. 2021-01-18 04:11:10 +08:00
ChsBuffer
46643a3f5e Fix: Detection Tick be enabled by MainForm.State even disabled by value 0 2021-01-18 04:06:28 +08:00
ChsBuffer
99752d7a44 Refactor Check settings change
Refactor Check Detection Tick value
Fix sometimes Detection Tick not update
2021-01-18 01:01:07 +08:00
ChsBuffer
004b84ceda Fix #498 2021-01-16 22:40:05 +08:00
218 changed files with 6820 additions and 44372 deletions

View File

@@ -12,6 +12,7 @@ tab_width = 4
# Microsoft .NET properties
csharp_new_line_before_members_in_object_initializers = false
csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion
csharp_space_after_cast = false
csharp_style_var_elsewhere = true:suggestion
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
@@ -27,22 +28,60 @@ dotnet_style_qualification_for_property = false:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
# ReSharper properties
resharper_align_multiline_switch_expression = false
resharper_align_multline_type_parameter_constrains = true
resharper_blank_lines_after_block_statements = 0
resharper_blank_lines_after_multiline_statements = 1
resharper_blank_lines_around_field = 1
resharper_blank_lines_around_invocable = 1
resharper_blank_lines_around_single_line_auto_property = 1
resharper_blank_lines_around_single_line_invocable = 0
resharper_blank_lines_around_single_line_property = 1
resharper_blank_lines_around_single_line_type = 0
resharper_blank_lines_around_type = 1
resharper_braces_for_lock = not_required
resharper_csharp_blank_lines_around_field = 0
resharper_csharp_blank_lines_around_invocable = 0
resharper_csharp_blank_lines_around_type = 0
resharper_csharp_blank_lines_around_single_line_invocable = 0
resharper_csharp_int_align_comments = true
resharper_csharp_keep_blank_lines_in_declarations = 1
resharper_csharp_max_line_length = 368
resharper_csharp_wrap_lines = false
resharper_csharp_max_line_length = 150
resharper_csharp_stick_comment = false
resharper_csharp_wrap_arguments_style = chop_if_long
resharper_csharp_wrap_multiple_type_parameter_constraints_style = chop_always
resharper_csharp_wrap_parameters_style = chop_if_long
resharper_indent_anonymous_method_block = false
resharper_int_align = false
resharper_keep_existing_declaration_parens_arrangement = false
resharper_keep_existing_embedded_arrangement = false
resharper_keep_existing_expr_member_arrangement = false
resharper_keep_existing_initializer_arrangement = true
resharper_keep_existing_linebreaks = false
resharper_keep_existing_property_patterns_arrangement = true
resharper_keep_existing_switch_expression_arrangement = false
resharper_max_array_initializer_elements_on_line = 7
resharper_max_formal_parameters_on_line = 7
resharper_max_initializer_elements_on_line = 1
resharper_max_invocation_arguments_on_line = 7
resharper_nested_ternary_style = compact
resharper_place_attribute_on_same_line = false
resharper_place_expr_accessor_on_single_line = true
resharper_place_expr_method_on_single_line = true
resharper_place_expr_property_on_single_line = true
resharper_place_field_attribute_on_same_line = false
resharper_place_linq_into_on_new_line = false
resharper_place_simple_embedded_statement_on_same_line = false
resharper_place_simple_initializer_on_single_line = false
resharper_place_simple_initializer_on_single_line = true
resharper_place_simple_switch_expression_on_single_line = true
resharper_show_autodetect_configure_formatting_tip = false
resharper_space_around_arrow_op = true
resharper_space_within_single_line_array_initializer_braces = true
resharper_use_indent_from_vs = false
resharper_wrap_array_initializer_style = chop_if_long
resharper_wrap_object_and_collection_initializer_style = chop_always
resharper_wrap_array_initializer_style = wrap_if_long
resharper_wrap_before_arrow_with_expressions = true
resharper_wrap_chained_method_calls = chop_if_long
resharper_wrap_object_and_collection_initializer_style = wrap_if_long
resharper_wrap_switch_expression = chop_if_long
resharper_wrap_verbatim_interpolated_strings = chop_if_long
# ReSharper inspection severities
resharper_arrange_redundant_parentheses_highlighting = hint

1
.gitattributes vendored Normal file
View File

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

View File

@@ -1,32 +0,0 @@
---
name: 'Bug report'
about: 'Create a report to help us improve'
title: ''
labels: '需要核实'
assignees: ''
---
**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.**
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Open Netch
2. ...
**Log**
Attaching any log files in the folder `Netch\logging` is strongly recommended.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- OS: [e.g. Windows 10 Pro 64-bit 1903]
- Netch Version: [e.g. 1.0.0-STABLE.x64]
**Additional context**
Add any other context about the problem here.

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

@@ -0,0 +1,51 @@
name: Bug report
description: Create a report to help us improve
labels: bug
body:
- 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: |
1. Open Netch
2. ...
validations:
required: true
- type: checkboxes
id: captcha
attributes:
label: CAPTCHA
description: Please confirm the options below.
options:
- label: 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.
required: true
- type: textarea
id: log
attributes:
label: Log
description: Attaching any log files in the folder `logging` is strongly recommended.
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment
render: txt
placeholder: |
- OS: [e.g. Windows 10 x64 Professional Workstation 20H2 19042.928]
- Netch Version: [e.g. 1.0.0]
validations:
required: true
- type: textarea
id: info
attributes:
label: Additional information
description: >
If you have any additional information for us, use the field below.

View File

@@ -1,29 +0,0 @@
---
name: '错误报告'
about: '创建错误报告以帮助我们改进'
title: ''
labels: '需要核实'
assignees: ''
---
**确保你已经看过 readme也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**
**错误描述**
对错误的清晰简洁描述
**复现步骤**
1. 打开 Netch 软件
2. ...
**日志**
强烈建议附上任何在 `Netch\logging` 文件夹下面的日志。
**错误截图**
如果适用,请添加屏幕截图以帮助解释您的问题
**信息**
- 操作系统:[例如 Windows 10 专业版 64 位 1903]
- 软件版本:[例如 1.0.0-STABLE 64 位]
**额外信息**

View File

@@ -0,0 +1,43 @@
name: 错误报告
description: 创建错误报告以帮助我们改进
labels: bug
body:
- type: textarea
id: error
attributes:
label: 错误描述
description: 对错误的清晰简洁描述
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: 复现步骤
placeholder: |
1. 打开 Netch 软件
2. ...
validations:
required: true
- type: textarea
id: log
attributes:
label: 日志
description: 强烈建议附上任何在 `logging` 文件夹下面的日志
validations:
required: true
- type: textarea
id: environment
attributes:
label: 操作环境
render: txt
placeholder: |
操作系统:[Windows 10 x64 Professional Workstation 20H2 19042.928]
软件版本:[1.0.0]
validations:
required: true
- type: textarea
id: info
attributes:
label: 额外信息
description: >
下面的文本框中你可以附上跟 issue 相关的截图、文件

View File

@@ -1,8 +1,9 @@
blank_issues_enabled: false
contact_links:
- name: Telegram Channel
url: https://t.me/Netch
url: https://t.me/netch_channel
about: Telegram Channel
- name: Telegram Group
url: https://t.me/Netch_Discuss_Group
about: Telegram Group
url: https://t.me/netch_group
about: Telegram Group

View File

@@ -1,16 +0,0 @@
---
name: 'Feature request'
about: 'Suggest an idea for this project'
title: ''
labels: 'Status: Review Needed'
assignees: ''
---
**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.**
**Describe the feature you want**
A clear and concise description of what you want to happen.
**Additional context** (Optional)
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,11 @@
name: Feature request
description: Suggest an idea for this project
labels: enhancement
body:
- 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

@@ -1,15 +0,0 @@
---
name: '功能请求'
about: '建议这个项目的想法'
title: ''
labels: 'Status: Review Needed'
assignees: ''
---
**确保你已经看过 readme也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**
**功能描述**
简明扼要地描述需要的功能
**额外信息**

View File

@@ -0,0 +1,11 @@
name: 功能请求
description: 建议这个项目的想法
labels: enhancement
body:
- type: textarea
id: description
attributes:
label: 功能描述
description: 简明扼要地描述需要的功能
validations:
required: true

21
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
time: "00:00"
timezone: "Asia/Shanghai"
labels:
- "automatic"
open-pull-requests-limit: 114514
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "daily"
time: "00:10"
timezone: "Asia/Shanghai"
labels:
- "automatic"
open-pull-requests-limit: 114514

View File

@@ -1,58 +1,27 @@
name: Netch CI
name: Netch Build CI
on: [push, pull_request]
jobs:
build:
name: Build
runs-on: windows-latest
steps:
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1.0.2
- name: MSBuild
uses: microsoft/setup-msbuild@v1.0.2
- name: Checkout
uses: actions/checkout@v2
with:
submodules: true
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Build Solution
shell: pwsh
run: .\BUILD.ps1
- name: Build
shell: pwsh
run: |
.\build.ps1 -Configuration Release -OutputPath release
- 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
- name: Package
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
shell: pwsh
run: |
New-Item -ItemType Directory -Path C:\builtfiles -Force > $null
7z a -mx9 C:\builtfiles\Netch.7z .\Netch\bin\x64\Release\
7z rn C:\builtfiles\Netch.7z Release Netch
echo "Netch_SHA256=$(.\GetSHA256.ps1 C:\builtfiles\Netch.7z)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "Netch_EXE_SHA256=$(.\GetSHA256.ps1 Netch\bin\x64\Release\Netch.exe)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
with:
name: ${{ env.GITHUB_TAG_NAME }}
prerelease: true
draft: false
files: |
C:\builtfiles\Netch.7z
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)
## 更新日志
* 这是 GitHub Actions 自动化部署,更新日志应该很快会手动更新
## 校验和
| 文件名 | SHA256 |
| :- | :- |
| Netch.7z | ${{ env.Netch_SHA256 }} |
- name: Upload
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: actions/upload-artifact@v2
with:
name: Netch
path: release

51
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: Netch Release CI
on:
push:
tags:
- '*.*.*'
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: Package
shell: pwsh
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
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
prerelease: ${{ contains(github.ref, '-') }}
draft: false
files: |
Netch.7z
body: |
[![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/netch_channel) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/netch_group)
## 更新日志
* 这是 GitHub Actions 自动化部署,更新日志应该很快会手动更新
## 校验和
| 文件名 | SHA256 |
| :- | :- |
| Netch.7z | ${{ env.Netch_SHA256 }} |

6
.gitignore vendored
View File

@@ -1,3 +1,5 @@
/.vs
/packages
.idea/
/.vscode
/.idea
/release
/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,12 +0,0 @@
Write-Host 'Building'
msbuild -v:n -m:1 /p:Configuration="Release" `
/p:Platform="x64" `
/p:TargetFramework=net48 `
/p:SolutionDir="..\" `
/restore `
Netch\Netch.csproj
if ($LASTEXITCODE) { exit $LASTEXITCODE }
Write-Host 'Build done'

View File

@@ -1,21 +0,0 @@
if (Test-Path Netch\bin)
{
Remove-Item -Recurse -Force Netch\bin
}
if (Test-Path Netch\obj)
{
Remove-Item -Recurse -Force Netch\obj
}
if (Test-Path NetchLib\bin)
{
Remove-Item -Recurse -Force NetchLib\bin
}
if (Test-Path NetchLib\obj)
{
Remove-Item -Recurse -Force NetchLib\obj
}
exit 0

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,6 +0,0 @@
param([string]$file)
$hash = [Security.Cryptography.HashAlgorithm]::Create( "SHA256" )
$path = (Resolve-Path -Path $file).Path
$stream = ([IO.StreamReader]$path).BaseStream
-join ($hash.ComputeHash($stream) | ForEach-Object { "{0:x2}" -f $_ })
$stream.Close()

View File

@@ -5,12 +5,6 @@ VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetchLib", "NetchLib\NetchLib.csproj", "{A8715AF4-ACC6-43F9-9381-4294C5360623}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetchUpdater", "NetchUpdater\NetchUpdater.csproj", "{828318A8-9B90-4A5F-BD6B-E632CC9D8933}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{53397641-35CA-4336-8E22-2CE12EF476AC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -21,17 +15,6 @@ Global
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.Build.0 = Debug|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.ActiveCfg = Release|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Debug|x64.ActiveCfg = Debug|x64
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Debug|x64.Build.0 = Debug|x64
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Release|x64.ActiveCfg = Release|x64
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Release|x64.Build.0 = Release|x64
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Debug|x64.ActiveCfg = Debug|x64
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Debug|x64.Build.0 = Debug|x64
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Release|x64.ActiveCfg = Release|x64
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Release|x64.Build.0 = Release|x64
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.ActiveCfg = Debug|x64
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.Build.0 = Debug|x64
{53397641-35CA-4336-8E22-2CE12EF476AC}.Release|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

2
Netch/.gitignore vendored
View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>
</configuration>

13
Netch/Constants.cs Normal file
View File

@@ -0,0 +1,13 @@
namespace Netch
{
public static class Constants
{
public const string EOF = "\r\n";
public static class Parameter
{
public const string Show = "-show";
public const string ForceUpdate = "-forceUpdate";
}
}
}

View File

@@ -1,6 +1,7 @@
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System;
using System.IO;
using Netch.Interfaces;
using static Netch.Interops.AioDNS;
namespace Netch.Controllers
{
@@ -8,48 +9,27 @@ namespace Netch.Controllers
{
public string Name { get; } = "DNS Service";
private const string RulePath = "bin\\aiodns.conf";
public void Stop()
{
Free();
}
/// <summary>
/// 启动DNS服务
/// </summary>
/// <returns></returns>
public bool Start()
public void Start()
{
aiodns_dial((int) NameList.TYPE_REST, null);
aiodns_dial((int) NameList.TYPE_ADDR, Encoding.UTF8.GetBytes($"{Global.Settings.LocalAddress}:53"));
aiodns_dial((int) NameList.TYPE_LIST, Encoding.UTF8.GetBytes(Path.GetFullPath(Global.Settings.AioDNS.RulePath)));
aiodns_dial((int) NameList.TYPE_CDNS, Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.ChinaDNS}:53"));
aiodns_dial((int) NameList.TYPE_ODNS, Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.OtherDNS}:53"));
aiodns_dial((int) NameList.TYPE_METH, Encoding.UTF8.GetBytes(Global.Settings.AioDNS.Protocol));
Dial(NameList.TYPE_REST, "");
Dial(NameList.TYPE_ADDR, $"{Global.Settings.LocalAddress}:{Global.Settings.AioDNS.ListenPort}");
Dial(NameList.TYPE_LIST, Path.GetFullPath(RulePath));
Dial(NameList.TYPE_CDNS, $"{Global.Settings.AioDNS.ChinaDNS}");
Dial(NameList.TYPE_ODNS, $"{Global.Settings.AioDNS.OtherDNS}");
return aiodns_init();
if (!Init())
throw new Exception("AioDNS start failed");
}
public void Stop()
{
aiodns_free();
}
#region NativeMethods
[DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool aiodns_dial(int name, byte[] value);
[DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool aiodns_init();
[DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern void aiodns_free();
enum NameList : int
{
TYPE_REST,
TYPE_ADDR,
TYPE_LIST,
TYPE_CDNS,
TYPE_ODNS,
TYPE_METH
}
#endregion
}
}

View File

@@ -1,3 +1,5 @@
using Netch.Models;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -6,15 +8,36 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Netch.Models;
using Netch.Utils;
using System.Threading.Tasks;
using Timer = System.Timers.Timer;
namespace Netch.Controllers
{
public abstract class Guard
{
public abstract string Name { get; protected set; }
private readonly Timer _flushFileStreamTimer = new(300) { AutoReset = true };
private FileStream? _logFileStream;
private StreamWriter? _logStreamWriter;
private bool _redirectToFile = true;
/// <summary>
/// 日志文件(重定向输出文件)
/// </summary>
protected string LogPath => Path.Combine(Global.NetchDir, $"logging\\{Name}.log");
/// <summary>
/// 成功启动关键词
/// </summary>
protected virtual IEnumerable<string> StartedKeywords { get; set; } = new List<string>();
/// <summary>
/// 启动失败关键词
/// </summary>
protected virtual IEnumerable<string> StoppedKeywords { get; set; } = new List<string>();
public abstract string Name { get; }
/// <summary>
/// 主程序名
@@ -23,40 +46,28 @@ namespace Netch.Controllers
protected State State { get; set; } = State.Waiting;
public abstract void Stop();
/// <summary>
/// 成功启动关键词
/// </summary>
protected readonly List<string> StartedKeywords = new List<string>();
/// <summary>
/// 启动失败关键词
/// </summary>
protected readonly List<string> StoppedKeywords = new List<string>();
/// <summary>
/// 进程是否可以重定向输出
/// </summary>
protected bool RedirectStd { get; set; } = true;
protected bool RedirectToFile
{
get => RedirectStd && _redirectToFile;
set => _redirectToFile = value;
}
/// <summary>
/// 进程实例
/// </summary>
public Process Instance { get; private set; }
/// <summary>
/// 日志文件(重定向输出文件)
/// </summary>
private string _logPath;
private readonly StringBuilder _logBuffer = new StringBuilder();
public Process? Instance { get; private set; }
/// <summary>
/// 程序输出的编码,
/// 调用于基类的 <see cref="OnOutputDataReceived"/>
/// </summary>
protected Encoding InstanceOutputEncoding { get; set; } = Encoding.GetEncoding("gbk");
protected virtual Encoding? InstanceOutputEncoding { get; } = null;
public abstract void Stop();
/// <summary>
/// 停止进程
@@ -65,13 +76,15 @@ namespace Netch.Controllers
{
try
{
if (Instance == null || Instance.HasExited) return;
if (Instance == null || Instance.HasExited)
return;
Instance.Kill();
Instance.WaitForExit();
}
catch (Win32Exception e)
{
Logging.Error($"停止 {MainFile} 错误:\n" + e);
Global.Logger.Error($"停止 {MainFile} 错误:\n" + e);
}
catch
{
@@ -80,10 +93,10 @@ namespace Netch.Controllers
}
/// <summary>
/// 仅初始化 <see cref="Instance"/>,不设定事件处理方法
/// 仅初始化 <see cref="Instance" />,不设定事件处理方法
/// </summary>
/// <param name="argument"></param>
protected void InitInstance(string argument)
protected virtual void InitInstance(string argument)
{
Instance = new Process
{
@@ -101,8 +114,10 @@ namespace Netch.Controllers
WindowStyle = ProcessWindowStyle.Hidden
}
};
}
if (!File.Exists(Instance.StartInfo.FileName))
throw new MessageException(i18N.Translate($"bin\\{MainFile} file not found!"));
}
/// <summary>
/// 默认行为启动主程序
@@ -110,129 +125,158 @@ namespace Netch.Controllers
/// <param name="argument">主程序启动参数</param>
/// <param name="priority">进程优先级</param>
/// <returns>是否成功启动</returns>
protected bool StartInstanceAuto(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal)
protected void StartInstanceAuto(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal)
{
State = State.Starting;
try
// 初始化程序
InitInstance(argument);
if (RedirectToFile)
OpenLogFile();
// 启动程序
Instance!.Start();
if (priority != ProcessPriorityClass.Normal)
Instance.PriorityClass = priority;
if (RedirectStd)
{
// 初始化程序
InitInstance(argument);
Instance.EnableRaisingEvents = true;
if (RedirectStd)
Task.Run(() => ReadOutput(Instance.StandardOutput));
Task.Run(() => ReadOutput(Instance.StandardError));
if (!StartedKeywords.Any())
{
// 清理日志
_logPath ??= Path.Combine(Global.NetchDir, $"logging\\{Name}.log");
if (File.Exists(_logPath))
File.Delete(_logPath);
Instance.OutputDataReceived += OnOutputDataReceived;
Instance.ErrorDataReceived += OnOutputDataReceived;
State = State.Started;
return;
}
Instance.Exited += OnExited;
// 启动程序
Instance.Start();
if (priority != ProcessPriorityClass.Normal)
Instance.PriorityClass = priority;
if (!RedirectStd) return true;
// 启动日志重定向
Instance.BeginOutputReadLine();
Instance.BeginErrorReadLine();
SaveBufferTimer.Elapsed += SaveBufferTimerEvent;
SaveBufferTimer.Enabled = true;
if (StartedKeywords.Count == 0) return true;
// 等待启动
for (var i = 0; i < 1000; i++)
{
Thread.Sleep(10);
switch (State)
{
case State.Started:
return true;
case State.Stopped:
Logging.Error($"{Name} 控制器启动失败");
Stop();
return false;
}
}
Logging.Error($"{Name} 控制器启动超时");
Stop();
return false;
}
catch (Exception e)
else
{
Logging.Error($"{Name} 控制器启动失败:\n {e}");
return false;
return;
}
// 等待启动
for (var i = 0; i < 1000; i++)
{
Thread.Sleep(10);
switch (State)
{
case State.Started:
Task.Run(OnKeywordStarted);
return;
case State.Stopped:
Stop();
CloseLogFile();
OnKeywordStopped();
throw new MessageException($"{Name} 控制器启动失败");
}
}
Stop();
OnKeywordTimeout();
throw new MessageException($"{Name} 控制器启动超时");
}
#region FileStream
private void OpenLogFile()
{
if (!RedirectToFile)
return;
_logFileStream = File.Open(LogPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
_logStreamWriter = new StreamWriter(_logFileStream);
_flushFileStreamTimer.Elapsed += FlushFileStreamTimerEvent;
_flushFileStreamTimer.Enabled = true;
}
private void WriteLog(string line)
{
if (!RedirectToFile)
return;
_logStreamWriter!.WriteLine(line);
}
private readonly object LogStreamLock = new();
private void CloseLogFile()
{
if (!RedirectToFile)
return;
lock (LogStreamLock)
{
if (_logFileStream == null)
return;
_flushFileStreamTimer.Enabled = false;
_logStreamWriter?.Close();
_logFileStream?.Close();
_logStreamWriter = _logStreamWriter = null;
}
}
private static readonly Timer SaveBufferTimer = new Timer(300) {AutoReset = true};
#endregion
private void OnExited(object sender, EventArgs e)
#region virtual
protected virtual void OnReadNewLine(string line)
{
if (RedirectStd)
}
protected virtual void OnKeywordStarted()
{
}
protected virtual void OnKeywordStopped()
{
Utils.Utils.Open(LogPath);
}
protected virtual void OnKeywordTimeout()
{
}
#endregion
protected void ReadOutput(TextReader reader)
{
string? line;
while ((line = reader.ReadLine()) != null)
{
SaveBufferTimer.Enabled = false;
WriteLog(line);
OnReadNewLine(line);
// State == State.Started if !StartedKeywords.Any()
if (State == State.Starting)
{
if (StartedKeywords.Any(s => line.Contains(s)))
State = State.Started;
else if (StoppedKeywords.Any(s => line.Contains(s)))
State = State.Stopped;
}
}
SaveBufferTimerEvent(null, null);
CloseLogFile();
State = State.Stopped;
}
/// <summary>
/// 接收输出数据
/// </summary>
/// <param name="sender">发送者</param>
/// <param name="e">数据</param>
protected void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
{
// 程序结束, 接收到 null
if (e.Data == null)
return;
Write(e.Data);
// 检查启动
if (State == State.Starting)
{
if (StartedKeywords.Any(s => e.Data.Contains(s)))
State = State.Started;
else if (StoppedKeywords.Any(s => e.Data.Contains(s)))
State = State.Stopped;
}
}
/// <summary>
/// 计时器存储日志
/// 计时器存储日志
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SaveBufferTimerEvent(object sender, EventArgs e)
private void FlushFileStreamTimerEvent(object sender, EventArgs e)
{
try
{
if (_logPath != null && _logBuffer != null)
{
File.AppendAllText(_logPath, _logBuffer.ToString());
_logBuffer.Clear();
}
_logStreamWriter!.Flush();
}
catch (Exception exception)
{
Logging.Warning($"写入 {Name} 日志错误:\n" + exception.Message);
Global.Logger.Warning($"写入 {Name} 日志错误:\n" + exception.Message);
}
}
/// <summary>
/// 写入日志文件缓冲
/// </summary>
/// <param name="info"></param>
/// <returns>转码后的字符串</returns>
private void Write(string info)
{
_logBuffer.Append(info + Global.EOF);
}
}
}

View File

@@ -1,141 +0,0 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Forms;
using WindowsProxy;
using Microsoft.Win32;
using Netch.Forms;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Servers.Trojan;
using Netch.Utils;
using Netch.Utils.HttpProxyHandler;
namespace Netch.Controllers
{
public class HTTPController : IModeController
{
public const string IEProxyExceptions = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
public PrivoxyController pPrivoxyController = new();
private string prevBypass, prevHTTP, prevPAC;
private bool prevEnabled;
public string Name { get; } = "HTTP";
/// <summary>
/// 启动
/// </summary>
/// <param name="mode">模式</param>
/// <returns>是否启动成功</returns>
public bool Start(in Mode mode)
{
RecordPrevious();
try
{
if (pPrivoxyController.Start(MainController.Server, mode))
Global.Job.AddProcess(pPrivoxyController.Instance);
if (mode.Type == 3)
{
if (MainController.Server is Socks5 or Trojan && mode.BypassChina)
{
//启动PAC服务器
PACServerHandle.InitPACServer("127.0.0.1");
}
else
{
using var service = new ProxyService
{
Server = $"127.0.0.1:{Global.Settings.HTTPLocalPort}",
Bypass = IEProxyExceptions
};
service.Global();
}
}
}
catch (Exception e)
{
if (MessageBoxX.Show(i18N.Translate("Failed to set the system proxy, it may be caused by the lack of dependent programs. Do you want to jump to Netch's official website to download dependent programs?"), confirm: true) == DialogResult.OK) Process.Start("https://netch.org/#/?id=%e4%be%9d%e8%b5%96");
Logging.Error("设置系统代理失败" + e);
return false;
}
return true;
}
/// <summary>
/// 停止
/// </summary>
public void Stop()
{
var tasks = new[]
{
Task.Run(pPrivoxyController.Stop),
Task.Run(() =>
{
using var service = new ProxyService();
try
{
PACServerHandle.Stop();
if (prevEnabled)
{
if (prevHTTP != "")
{
service.Server = prevHTTP;
service.Bypass = prevBypass;
service.Global();
}
if (prevPAC != "")
{
service.AutoConfigUrl = prevPAC;
service.Pac();
}
}
else
{
service.Direct();
}
}
catch (Exception e)
{
Logging.Error($"{Name} 控制器出错:\n" + e);
}
})
};
Task.WaitAll(tasks);
}
private void RecordPrevious()
{
try
{
var registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
if (registry == null)
throw new Exception();
prevPAC = registry.GetValue("AutoConfigURL")?.ToString() ?? "";
prevHTTP = registry.GetValue("ProxyServer")?.ToString() ?? "";
prevBypass = registry.GetValue("ProxyOverride")?.ToString() ?? "";
prevEnabled = registry.GetValue("ProxyEnable")?.Equals(1) ?? false; // HTTP Proxy Enabled
if (prevHTTP == $"127.0.0.1:{Global.Settings.HTTPLocalPort}")
{
prevEnabled = false;
prevHTTP = "";
}
if (prevPAC != "")
prevEnabled = true;
}
catch
{
prevEnabled = false;
prevPAC = prevHTTP = prevBypass = "";
}
}
}
}

View File

@@ -1,51 +1,45 @@
using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Netch.Forms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using static Netch.Forms.MainForm;
using static Netch.Utils.PortHelper;
namespace Netch.Controllers
{
public static class MainController
{
public static Mode Mode;
public static Mode? Mode;
/// TCP or Both Server
public static Server Server;
public static Server? Server;
private static Server _udpServer;
private static Server? _udpServer;
public static bool NttTested;
public static readonly NTTController NTTController = new();
private static IServerController? _serverController;
private static IServerController? _udpServerController;
private static readonly NTTController NTTController = new();
private static IServerController _serverController;
private static IServerController _udpServerController;
public static IServerController ServerController
public static IServerController? ServerController
{
get => _serverController;
private set => _serverController = value;
}
public static IServerController UdpServerController
public static IServerController? UdpServerController
{
get => _udpServerController ?? _serverController;
set => _udpServerController = value;
}
public static Server UdpServer
public static Server? UdpServer
{
get => _udpServer ?? Server;
set => _udpServer = value;
}
public static IModeController ModeController { get; private set; }
public static IModeController? ModeController { get; private set; }
/// <summary>
/// 启动
@@ -53,149 +47,102 @@ namespace Netch.Controllers
/// <param name="server">服务器</param>
/// <param name="mode">模式</param>
/// <returns>是否启动成功</returns>
public static async Task<bool> Start(Server server, Mode mode)
/// <exception cref="MessageException"></exception>
public static async Task StartAsync(Server server, Mode mode)
{
Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}");
await Task.Run(() => Start(server, mode));
}
public static void Start(Server server, Mode mode)
{
Global.Logger.Info($"启动主控制器: {server.Type} [{(int)mode.Type}]{mode.Remark}");
Server = server;
Mode = mode;
if (server is Socks5 && mode.Type == 4)
return false;
// 刷新 DNS 缓存
NativeMethods.RefreshDNSCache();
// 刷新DNS缓存
NativeMethods.FlushDNSResolverCache();
if (DnsUtils.Lookup(server.Hostname) == null)
throw new MessageException(i18N.Translate("Lookup Server hostname failed"));
try
{
WebUtil.BestLocalEndPoint(new IPEndPoint(0x72727272, 53));
}
catch (Exception)
{
MessageBoxX.Show("No internet connection");
return false;
}
if (Global.Settings.ResolveServerHostname && DNS.Lookup(server.Hostname) == null)
{
MessageBoxX.Show("Lookup Server hostname failed");
return false;
}
// 添加Netch到防火墙
_ = Task.Run(Firewall.AddNetchFwRules);
// 添加 Netch 到防火墙
Firewall.AddNetchFwRules();
try
{
if (!ModeHelper.SkipServerController(server, mode))
{
if (!await Task.Run(() => StartServer(server, mode, ref _serverController)))
throw new StartFailedException();
StartServer(server, mode, out _serverController);
StatusPortInfoText.UpdateShareLan();
}
if (!await StartMode(mode))
throw new StartFailedException();
_ = Task.Run(Bandwidth.NetTraffic);
_ = Task.Run(NatTest);
return true;
StartMode(mode);
}
catch (Exception e)
{
Stop();
switch (e)
{
case DllNotFoundException _:
case FileNotFoundException _:
MessageBoxX.Show(e.Message + "\n\n" + i18N.Translate("Missing File or runtime components"), owner: Global.MainForm);
break;
case StartFailedException _:
break;
case DllNotFoundException:
case FileNotFoundException:
throw new Exception(e.Message + "\n\n" + i18N.Translate("Missing File or runtime components"));
case MessageException:
throw;
default:
Logging.Error($"主控制器未处理异常: {e}");
break;
Global.Logger.Error(e.ToString());
Global.Logger.ShowLog();
throw new MessageException($"未处理异常\n{e.Message}");
}
try
{
await Stop();
}
catch
{
// ignored
}
return false;
}
}
private static bool StartServer(Server server, Mode mode, ref IServerController controller)
private static void StartServer(Server server, Mode mode, out IServerController controller)
{
controller = ServerHelper.GetUtilByTypeName(server.Type).GetController();
if (controller is Guard instanceController)
Utils.Utils.KillProcessByName(instanceController.MainFile);
if (!PortCheckAndShowMessageBox(controller.Socks5LocalPort(), "Socks5"))
return false;
TryReleaseTcpPort(controller.Socks5LocalPort(), "Socks5");
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name));
if (controller.Start(in server, mode))
controller.Start(in server, mode);
if (server is Socks5 socks5)
{
if (controller is Guard guard)
if (guard.Instance != null)
Task.Run(() =>
{
Thread.Sleep(1000);
Global.Job.AddProcess(guard.Instance);
});
if (server is Socks5 socks5)
{
if (socks5.Auth())
StatusPortInfoText.Socks5Port = controller.Socks5LocalPort();
}
else
{
if (socks5.Auth())
StatusPortInfoText.Socks5Port = controller.Socks5LocalPort();
}
return true;
}
return false;
else
{
StatusPortInfoText.Socks5Port = controller.Socks5LocalPort();
}
}
private static async Task<bool> StartMode(Mode mode)
private static void StartMode(Mode mode)
{
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType);
if (ModeController == null)
return true;
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName);
if (port != null)
if (!PortCheckAndShowMessageBox((ushort) port, portName, portType))
return false;
TryReleaseTcpPort((ushort)port, portName);
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
if (await Task.Run(() => ModeController.Start(mode)))
{
if (ModeController is Guard guard)
if (guard.Instance != null)
Global.Job.AddProcess(guard.Instance);
return true;
}
ModeController.Start(mode);
}
return false;
public static async Task StopAsync()
{
await Task.Run(Stop);
}
/// <summary>
/// 停止
/// </summary>
public static async Task Stop()
public static void Stop()
{
if (_serverController == null && ModeController == null)
return;
StatusPortInfoText.Reset();
_ = Task.Run(() => NTTController.Stop());
@@ -205,64 +152,57 @@ namespace Netch.Controllers
Task.Run(() => ServerController?.Stop()),
Task.Run(() => ModeController?.Stop())
};
await Task.WhenAll(tasks);
try
{
Task.WaitAll(tasks);
}
catch (Exception e)
{
Global.Logger.Error(e.ToString());
Global.Logger.ShowLog();
}
ModeController = null;
ServerController = null;
}
/// <summary>
/// 检查端口是否被占用,
/// 被占用则弹窗提示, 确认后抛出异常
/// </summary>
public static bool PortCheckAndShowMessageBox(ushort port, string portName, PortType portType = PortType.Both)
public static void PortCheck(ushort port, string portName, PortType portType = PortType.Both)
{
try
{
CheckPort(port, portType);
return true;
PortHelper.CheckPort(port, portType);
}
catch (PortInUseException)
{
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", $"{portName} ({port})"));
return false;
throw new MessageException(i18N.TranslateFormat("The {0} port is in use.", $"{portName} ({port})"));
}
catch (PortReservedException)
{
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is reserved by system.", $"{portName} ({port})"));
return false;
throw new MessageException(i18N.TranslateFormat("The {0} port is reserved by system.", $"{portName} ({port})"));
}
}
/// <summary>
/// 测试 NAT
/// </summary>
public static void NatTest()
public static void TryReleaseTcpPort(ushort port, string portName)
{
if (!Mode.TestNatRequired())
return;
NttTested = false;
Task.Run(() =>
foreach (var p in PortHelper.GetProcessByUsedTcpPort(port))
{
Global.MainForm.NatTypeStatusText(i18N.Translate("Starting NatTester"));
// Thread.Sleep(1000);
var (result, localEnd, publicEnd) = NTTController.Start();
var fileName = p.MainModule?.FileName;
if (fileName == null)
continue;
if (!string.IsNullOrEmpty(publicEnd))
if (fileName.StartsWith(Global.NetchDir))
{
var country = Utils.Utils.GetCityCode(publicEnd);
Global.MainForm.NatTypeStatusText(result, country);
p.Kill();
p.WaitForExit();
}
else
{
Global.MainForm.NatTypeStatusText(result ?? "Error");
throw new MessageException(i18N.TranslateFormat("The {0} port is used by {1}.", $"{portName} ({port})", $"({p.Id}){fileName}"));
}
}
NttTested = true;
});
PortCheck(port, portName, PortType.TCP);
}
}
public class StartFailedException : Exception
{
}
}

View File

@@ -2,15 +2,14 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Threading.Tasks;
using Netch.Forms;
using Netch.Interfaces;
using Netch.Interops;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5;
using Netch.Utils;
using nfapinet;
using static Netch.Interops.Redirector;
namespace Netch.Controllers
{
@@ -18,198 +17,89 @@ namespace Netch.Controllers
{
private static readonly ServiceController NFService = new("netfilter2");
private static readonly string BinDriver = string.Empty;
private const string BinDriver = "bin\\nfdriver.sys";
private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
private static string _sysDns;
static NFController()
{
string fileName;
switch ($"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}")
{
case "10.0":
fileName = "Win-10.sys";
break;
case "6.3":
case "6.2":
fileName = "Win-8.sys";
break;
case "6.1":
case "6.0":
fileName = "Win-7.sys";
break;
default:
Logging.Error($"不支持的系统版本:{Environment.OSVersion.Version}");
return;
}
BinDriver = "bin\\" + fileName;
}
public string Name { get; } = "Redirector";
public bool Start(in Mode mode)
public void Start(in Mode mode)
{
if (!CheckDriver())
return false;
CheckDriver();
#region aio_dial
Dial(NameList.TYPE_FILTERLOOPBACK, "false");
Dial(NameList.TYPE_FILTERICMP, "true");
var p = PortHelper.GetAvailablePort();
Dial(NameList.TYPE_TCPLISN, p.ToString());
Dial(NameList.TYPE_UDPLISN, p.ToString());
aio_dial((int) NameList.TYPE_FILTERLOOPBACK, "false");
aio_dial((int) NameList.TYPE_TCPLISN, Global.Settings.RedirectorTCPPort.ToString());
// Server
Dial(NameList.TYPE_FILTERUDP, (Global.Settings.Redirector.ProxyProtocol != PortType.TCP).ToString().ToLower());
Dial(NameList.TYPE_FILTERTCP, (Global.Settings.Redirector.ProxyProtocol != PortType.UDP).ToString().ToLower());
dial_Server(Global.Settings.Redirector.ProxyProtocol);
if (Global.Settings.ProcessNoProxyForUdp && Global.Settings.ProcessNoProxyForTcp) MessageBoxX.Show("");
// Mode Rule
dial_Name(mode);
//UDP
if (Global.Settings.ProcessNoProxyForUdp)
{
aio_dial((int) NameList.TYPE_FILTERUDP, "false");
SetServer(PortType.TCP);
}
else
{
aio_dial((int) NameList.TYPE_FILTERUDP, "true");
SetServer(PortType.Both);
}
// Features
Dial(NameList.TYPE_DNSHOST, Global.Settings.Redirector.DNSHijack ? Global.Settings.Redirector.DNSHijackHost : "");
//TCP
if (Global.Settings.ProcessNoProxyForTcp)
{
aio_dial((int) NameList.TYPE_FILTERTCP, "false");
SetServer(PortType.UDP);
}
else
{
aio_dial((int) NameList.TYPE_FILTERTCP, "true");
SetServer(PortType.Both);
}
if (!CheckRule(mode.FullRule, out var list))
{
MessageBoxX.Show($"\"{string.Join("", list.Select(s => s + "\n"))}\" does not conform to C++ regular expression syntax");
return false;
}
SetName(mode);
#endregion
if (Global.Settings.ModifySystemDNS)
{
// 备份并替换系统 DNS
_sysDns = DNS.OutboundDNS;
if (string.IsNullOrWhiteSpace(Global.Settings.ModifiedDNS))
Global.Settings.ModifiedDNS = "1.1.1.1,8.8.8.8";
DNS.OutboundDNS = Global.Settings.ModifiedDNS;
}
return aio_init();
if (!Init())
throw new MessageException("Redirector Start failed, run Netch with \"-console\" argument");
}
public void Stop()
{
Task.Run(() =>
{
if (Global.Settings.ModifySystemDNS)
//恢复系统DNS
DNS.OutboundDNS = _sysDns;
});
aio_free();
Free();
}
/// <summary>
/// </summary>
/// <param name="rules"></param>
/// <param name="incompatibleRule"></param>
/// <returns>No Problem true</returns>
public static bool CheckRule(IEnumerable<string> rules, out IEnumerable<string> incompatibleRule)
{
incompatibleRule = rules.Where(r => !CheckCppRegex(r, false));
aio_dial((int) NameList.TYPE_CLRNAME, "");
return !incompatibleRule.Any();
}
#region CheckRule
/// <summary>
/// </summary>
/// <param name="r"></param>
/// <param name="clear"></param>
/// <returns>No Problem true</returns>
public static bool CheckCppRegex(string r, bool clear = true)
private static bool CheckCppRegex(string r, bool clear = true)
{
try
{
if (r.StartsWith("!"))
return aio_dial((int) NameList.TYPE_ADDNAME, r.Substring(1));
return aio_dial((int) NameList.TYPE_ADDNAME, r);
return Dial(NameList.TYPE_ADDNAME, r.Substring(1));
return Dial(NameList.TYPE_ADDNAME, r);
}
finally
{
if (clear)
aio_dial((int) NameList.TYPE_CLRNAME, "");
Dial(NameList.TYPE_CLRNAME, "");
}
}
private static bool CheckDriver()
/// <summary>
/// </summary>
/// <param name="rules"></param>
/// <param name="results"></param>
/// <returns>No Problem true</returns>
public static bool CheckRules(IEnumerable<string> rules, out IEnumerable<string> results)
{
var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
Logging.Info("内置驱动版本: " + binFileVersion);
Logging.Info("系统驱动版本: " + systemFileVersion);
if (!File.Exists(BinDriver))
{
Logging.Warning("内置驱动不存在");
if (File.Exists(SystemDriver))
{
Logging.Warning("使用系统驱动");
return true;
}
Logging.Error("未安装驱动");
return false;
}
if (!File.Exists(SystemDriver))
return InstallDriver();
var updateFlag = false;
if (Version.TryParse(binFileVersion, out var binResult) && Version.TryParse(systemFileVersion, out var systemResult))
{
if (binResult.CompareTo(systemResult) > 0)
{
// Bin greater than Installed
updateFlag = true;
}
else
{
// Installed greater than Bin
if (systemResult.Major != binResult.Major)
// API breaking changes
updateFlag = true;
}
}
else
{
if (!systemFileVersion.Equals(binFileVersion))
updateFlag = true;
}
if (!updateFlag) return true;
Logging.Info("更新驱动");
UninstallDriver();
return InstallDriver();
results = rules.Where(r => !CheckCppRegex(r, false));
Dial(NameList.TYPE_CLRNAME, "");
return !results.Any();
}
private void SetServer(in PortType portType)
public static string GenerateInvalidRulesMessage(IEnumerable<string> rules)
{
return $"{string.Join("\n", rules)}\nAbove rules does not conform to C++ regular expression syntax";
}
#endregion
private void dial_Server(in PortType portType)
{
if (portType == PortType.Both)
{
SetServer(PortType.TCP);
SetServer(PortType.UDP);
dial_Server(PortType.TCP);
dial_Server(PortType.UDP);
return;
}
@@ -220,118 +110,128 @@ namespace Netch.Controllers
if (portType == PortType.UDP)
{
offset = UdpNameListOffset;
server = MainController.UdpServer;
controller = MainController.UdpServerController;
server = MainController.UdpServer!;
controller = MainController.UdpServerController!;
}
else
{
offset = 0;
server = MainController.Server;
controller = MainController.ServerController;
server = MainController.Server!;
controller = MainController.ServerController!;
}
if (server is Socks5 socks5)
{
aio_dial((int) NameList.TYPE_TCPTYPE + offset, "Socks5");
aio_dial((int) NameList.TYPE_TCPHOST + offset, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
aio_dial((int) NameList.TYPE_TCPUSER + offset, socks5.Username ?? string.Empty);
aio_dial((int) NameList.TYPE_TCPPASS + offset, socks5.Password ?? string.Empty);
aio_dial((int) NameList.TYPE_TCPMETH + offset, string.Empty);
Dial(NameList.TYPE_TCPTYPE + offset, "Socks5");
Dial(NameList.TYPE_TCPHOST + offset, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
Dial(NameList.TYPE_TCPUSER + offset, socks5.Username ?? string.Empty);
Dial(NameList.TYPE_TCPPASS + offset, socks5.Password ?? string.Empty);
Dial(NameList.TYPE_TCPMETH + offset, string.Empty);
}
else if (server is Shadowsocks shadowsocks && !shadowsocks.HasPlugin() && Global.Settings.RedirectorSS)
else if (server is Shadowsocks shadowsocks && !shadowsocks.HasPlugin() && Global.Settings.Redirector.RedirectorSS)
{
aio_dial((int) NameList.TYPE_TCPTYPE + offset, "Shadowsocks");
aio_dial((int) NameList.TYPE_TCPHOST + offset, $"{shadowsocks.AutoResolveHostname()}:{shadowsocks.Port}");
aio_dial((int) NameList.TYPE_TCPMETH + offset, shadowsocks.EncryptMethod ?? string.Empty);
aio_dial((int) NameList.TYPE_TCPPASS + offset, shadowsocks.Password ?? string.Empty);
Dial(NameList.TYPE_TCPTYPE + offset, "Shadowsocks");
Dial(NameList.TYPE_TCPHOST + offset, $"{shadowsocks.AutoResolveHostname()}:{shadowsocks.Port}");
Dial(NameList.TYPE_TCPMETH + offset, shadowsocks.EncryptMethod);
Dial(NameList.TYPE_TCPPASS + offset, shadowsocks.Password);
}
else
{
aio_dial((int) NameList.TYPE_TCPTYPE + offset, "Socks5");
aio_dial((int) NameList.TYPE_TCPHOST + offset, $"127.0.0.1:{controller.Socks5LocalPort()}");
aio_dial((int) NameList.TYPE_TCPUSER + offset, string.Empty);
aio_dial((int) NameList.TYPE_TCPPASS + offset, string.Empty);
aio_dial((int) NameList.TYPE_TCPMETH + offset, string.Empty);
Dial(NameList.TYPE_TCPTYPE + offset, "Socks5");
Dial(NameList.TYPE_TCPHOST + offset, $"127.0.0.1:{controller.Socks5LocalPort()}");
Dial(NameList.TYPE_TCPUSER + offset, string.Empty);
Dial(NameList.TYPE_TCPPASS + offset, string.Empty);
Dial(NameList.TYPE_TCPMETH + offset, string.Empty);
}
}
private void SetName(Mode mode)
private void dial_Name(Mode mode)
{
aio_dial((int) NameList.TYPE_CLRNAME, "");
foreach (var rule in mode.FullRule)
Dial(NameList.TYPE_CLRNAME, "");
var invalidList = new List<string>();
foreach (var s in mode.GetRules())
{
if (rule.StartsWith("!"))
if (s.StartsWith("!"))
{
aio_dial((int) NameList.TYPE_BYPNAME, rule.Substring(1));
if (!Dial(NameList.TYPE_BYPNAME, s.Substring(1)))
invalidList.Add(s);
continue;
}
aio_dial((int) NameList.TYPE_ADDNAME, rule);
if (!Dial(NameList.TYPE_ADDNAME, s))
invalidList.Add(s);
}
aio_dial((int) NameList.TYPE_ADDNAME, @"NTT\.exe");
if (invalidList.Any())
throw new MessageException(GenerateInvalidRulesMessage(invalidList));
Dial(NameList.TYPE_ADDNAME, @"NTT\.exe");
Dial(NameList.TYPE_BYPNAME, "^" + Global.NetchDir.ToRegexString() + @"((?!NTT\.exe).)*$");
}
#region NativeMethods
#region DriverUtil
private const int UdpNameListOffset = (int) NameList.TYPE_UDPTYPE - (int) NameList.TYPE_TCPTYPE;
[DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)]
private static extern bool aio_dial(int name, [MarshalAs(UnmanagedType.LPWStr)] string value);
[DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)]
private static extern bool aio_init();
[DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)]
private static extern bool aio_free();
[DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)]
private static extern ulong aio_getUP();
[DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)]
private static extern ulong aio_getDL();
public enum NameList
private static void CheckDriver()
{
TYPE_FILTERLOOPBACK,
TYPE_FILTERTCP,
TYPE_FILTERUDP,
TYPE_TCPLISN,
TYPE_TCPTYPE,
TYPE_TCPHOST,
TYPE_TCPUSER,
TYPE_TCPPASS,
TYPE_TCPMETH,
TYPE_UDPTYPE,
TYPE_UDPHOST,
TYPE_UDPUSER,
TYPE_UDPPASS,
TYPE_UDPMETH,
TYPE_ADDNAME,
TYPE_BYPNAME,
TYPE_CLRNAME
var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
Global.Logger.Info("内置驱动版本: " + binFileVersion);
Global.Logger.Info("系统驱动版本: " + systemFileVersion);
if (!File.Exists(SystemDriver))
{
// Install
InstallDriver();
return;
}
var reinstall = false;
if (Version.TryParse(binFileVersion, out var binResult) && Version.TryParse(systemFileVersion, out var systemResult))
{
if (binResult.CompareTo(systemResult) > 0)
// Update
reinstall = true;
else if (systemResult.Major != binResult.Major)
// Downgrade when Major version different (may have breaking changes)
reinstall = true;
}
else
{
// Parse File versionName to Version failed
if (!systemFileVersion.Equals(binFileVersion))
// versionNames are different, Reinstall
reinstall = true;
}
if (!reinstall)
return;
Global.Logger.Info("更新驱动");
UninstallDriver();
InstallDriver();
}
#endregion
#region Utils
/// <summary>
/// 安装 NF 驱动
/// </summary>
/// <returns>驱动是否安装成功</returns>
public static bool InstallDriver()
private static void InstallDriver()
{
Logging.Info("安装 NF 驱动");
Global.Logger.Info("安装 NF 驱动");
if (!File.Exists(BinDriver))
throw new MessageException(i18N.Translate("builtin driver files missing, can't install NF driver"));
try
{
File.Copy(BinDriver, SystemDriver);
}
catch (Exception e)
{
Logging.Error("驱动复制失败\n" + e);
return false;
Global.Logger.Error("驱动复制失败\n" + e);
throw new MessageException($"Copy NF driver file failed\n{e.Message}");
}
Global.MainForm.StatusText(i18N.Translate("Register driver"));
@@ -339,15 +239,13 @@ namespace Netch.Controllers
var result = NFAPI.nf_registerDriver("netfilter2");
if (result == NF_STATUS.NF_STATUS_SUCCESS)
{
Logging.Info("驱动安装成功");
Global.Logger.Info("驱动安装成功");
}
else
{
Logging.Error($"注册驱动失败,返回值:{result}");
return false;
Global.Logger.Error($"注册驱动失败,返回值:{result}");
throw new MessageException($"Register NF driver failed\n{result}");
}
return true;
}
/// <summary>
@@ -356,7 +254,7 @@ namespace Netch.Controllers
/// <returns>是否成功卸载</returns>
public static bool UninstallDriver()
{
Logging.Info("卸载 NF 驱动");
Global.Logger.Info("卸载 NF 驱动");
try
{
if (NFService.Status == ServiceControllerStatus.Running)
@@ -370,7 +268,9 @@ namespace Netch.Controllers
// ignored
}
if (!File.Exists(SystemDriver)) return true;
if (!File.Exists(SystemDriver))
return true;
NFAPI.nf_unRegisterDriver("netfilter2");
File.Delete(SystemDriver);

View File

@@ -1,47 +1,62 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Netch.Interfaces;
using Netch.Utils;
namespace Netch.Controllers
{
public class NTTController : Guard, IController
{
public override string Name { get; protected set; } = "NTT";
public override string MainFile { get; protected set; } = "NTT.exe";
public override string Name { get; } = "NTT";
public override void Stop()
{
StopInstance();
}
/// <summary>
/// 启动 NatTypeTester
/// </summary>
/// <returns></returns>
public (string, string, string) Start()
public async Task<(string? result, string? localEnd, string? publicEnd)> Start()
{
string localEnd=null;
string publicEnd=null;
string result =null;
string bindingTest=null;
string? localEnd = null, publicEnd = null, result = null, bindingTest = null;
try
{
InitInstance($" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}");
Instance.OutputDataReceived += OnOutputDataReceived;
Instance.ErrorDataReceived += OnOutputDataReceived;
Instance.Start();
var output = Instance.StandardOutput.ReadToEnd();
Instance!.Start();
var output = await Instance.StandardOutput.ReadToEndAsync();
var error = await Instance.StandardError.ReadToEndAsync();
try
{
File.WriteAllText(Path.Combine(Global.NetchDir, $"logging\\{Name}.log"), output);
await File.WriteAllTextAsync(Path.Combine(Global.NetchDir, $"logging\\{Name}.log"), $"{output}\r\n{error}");
}
catch (Exception e)
{
Logging.Warning($"写入 {Name} 日志错误:\n" + e.Message);
Global.Logger.Warning($"写入 {Name} 日志错误:\n" + e.Message);
}
if (output.IsNullOrWhiteSpace())
if (!error.IsNullOrWhiteSpace())
{
error = error.Trim();
var errorFirst = error.Substring(0, error.IndexOf('\n')).Trim();
return (errorFirst.SplitTrimEntries(':').Last(), null, null);
}
foreach (var line in output.Split('\n'))
{
var str = line.Split(':').Select(s => s.Trim()).ToArray();
var str = line.SplitTrimEntries(':');
if (str.Length < 2)
continue;
var key = str[0];
var value = str[1];
switch (key)
@@ -62,19 +77,17 @@ namespace Netch.Controllers
case "result":
result = value;
break;
default:
result = str.Last();
break;
}
}
if (bindingTest == "Fail")
result = "UdpBlocked";
result = "Fail";
return (result, localEnd, publicEnd);
}
catch (Exception e)
{
Logging.Error($"{Name} 控制器出错:\n" + e);
Global.Logger.Error($"{Name} 控制器出错:\n" + e);
try
{
Stop();
@@ -87,10 +100,5 @@ namespace Netch.Controllers
return (null, null, null);
}
}
public override void Stop()
{
StopInstance();
}
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Netch.Forms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
namespace Netch.Controllers
{
public class PcapController : Guard, IModeController
{
public override string Name { get; } = "pcap2socks";
public override string MainFile { get; protected set; } = "pcap2socks.exe";
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "└" };
protected override Encoding? InstanceOutputEncoding { get; } = Encoding.UTF8;
private LogForm? _form;
public void Start(in Mode mode)
{
var server = MainController.Server!;
_form = new LogForm(Global.MainForm);
_form.CreateControl();
var outboundNetworkInterface = NetworkInterfaceUtils.GetBest();
var argument = new StringBuilder($@"-i \Device\NPF_{outboundNetworkInterface.Id}");
if (server is Socks5 socks5 && !socks5.Auth())
argument.Append($" --destination {server.AutoResolveHostname()}:{server.Port}");
else
argument.Append($" --destination 127.0.0.1:{Global.Settings.Socks5LocalPort}");
argument.Append($" {mode.GetRules().FirstOrDefault() ?? "-P n"}");
StartInstanceAuto(argument.ToString());
}
protected override void OnReadNewLine(string line)
{
Global.MainForm.BeginInvoke(new Action(() =>
{
if (!_form!.IsDisposed)
_form.richTextBox1.AppendText(line + "\n");
}));
}
protected override void OnKeywordStarted()
{
Global.MainForm.BeginInvoke(new Action(() => { _form!.Show(); }));
}
protected override void OnKeywordStopped()
{
if (File.ReadAllText(LogPath).Length == 0)
{
Task.Run(() =>
{
Thread.Sleep(1000);
Utils.Utils.Open("https://github.com/zhxie/pcap2socks#dependencies");
});
throw new MessageException("Pleases install pcap2socks's dependency");
}
Utils.Utils.Open(LogPath);
}
public override void Stop()
{
_form!.Close();
StopInstance();
}
}
}

View File

@@ -1,45 +0,0 @@
using System.IO;
using System.Text;
using Netch.Models;
using Netch.Servers.Socks5;
namespace Netch.Controllers
{
public class PrivoxyController : Guard, IController
{
public PrivoxyController()
{
RedirectStd = false;
}
public override string Name { get; protected set; } = "Privoxy";
public override string MainFile { get; protected set; } = "Privoxy.exe";
public bool Start(Server server, Mode mode)
{
var text = new StringBuilder(File.ReadAllText("bin\\default.conf"));
text.Replace("_BIND_PORT_", Global.Settings.HTTPLocalPort.ToString());
text.Replace("0.0.0.0", Global.Settings.LocalAddress); /* BIND_HOST */
if (server is Socks5 socks5 && !socks5.Auth())
{
text.Replace("/ 127.0.0.1", $"/ {server.AutoResolveHostname()}"); /* DEST_HOST */
text.Replace("_DEST_PORT_", socks5.Port.ToString());
}
text.Replace("_DEST_PORT_", Global.Settings.Socks5LocalPort.ToString());
File.WriteAllText("data\\privoxy.conf", text.ToString());
return StartInstanceAuto("..\\data\\privoxy.conf");
}
public override void Stop()
{
StopInstance();
}
}
}

View File

@@ -0,0 +1,209 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using Netch.Interops;
using static Netch.Interops.tun2socks;
namespace Netch.Controllers
{
public class TUNController : IModeController
{
public string Name => "tun2socks";
private const string DummyDns = "6.6.6.6";
private readonly DNSController _aioDnsController = new();
private NetRoute _outbound;
private NetRoute _tun;
private IPAddress _serverAddresses = null!;
private Mode _mode = null!;
public void Start(in Mode mode)
{
_mode = mode;
var server = MainController.Server!;
_serverAddresses = DnsUtils.Lookup(server.Hostname)!; // server address have been cached when MainController.Start
IPAddress address;
(_outbound, address) = NetRoute.GetBestRouteTemplate();
CheckDriver();
Dial(NameList.TYPE_ADAPMTU, "1500");
Dial(NameList.TYPE_BYPBIND, address.ToString());
Dial(NameList.TYPE_BYPLIST, "disabled");
#region Server
Dial(NameList.TYPE_TCPREST, "");
Dial(NameList.TYPE_TCPTYPE, "Socks5");
Dial(NameList.TYPE_UDPREST, "");
Dial(NameList.TYPE_UDPTYPE, "Socks5");
if (server is Socks5 socks5)
{
Dial(NameList.TYPE_TCPHOST, $"{server.AutoResolveHostname()}:{server.Port}");
Dial(NameList.TYPE_UDPHOST, $"{server.AutoResolveHostname()}:{server.Port}");
if (socks5.Auth())
{
Dial(NameList.TYPE_TCPUSER, socks5.Username!);
Dial(NameList.TYPE_TCPPASS, socks5.Password!);
Dial(NameList.TYPE_UDPUSER, socks5.Username!);
Dial(NameList.TYPE_UDPPASS, socks5.Password!);
}
}
else
{
Dial(NameList.TYPE_TCPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}");
Dial(NameList.TYPE_UDPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}");
}
#endregion
#region DNS
if (Global.Settings.TUNTAP.UseCustomDNS)
{
Dial(NameList.TYPE_DNSADDR, Global.Settings.TUNTAP.HijackDNS);
}
else
{
MainController.PortCheck(Global.Settings.AioDNS.ListenPort, "DNS");
_aioDnsController.Start();
Dial(NameList.TYPE_DNSADDR, $"127.0.0.1:{Global.Settings.AioDNS.ListenPort}");
}
#endregion
if (!Init())
throw new MessageException("tun2socks start failed, reboot your system and start again.");
var tunIndex = (int)RouteHelper.ConvertLuidToIndex(tun_luid());
_tun = NetRoute.TemplateBuilder(Global.Settings.TUNTAP.Gateway, tunIndex);
RouteHelper.CreateUnicastIP(AddressFamily.InterNetwork,
Global.Settings.TUNTAP.Address,
(byte)Utils.Utils.SubnetToCidr(Global.Settings.TUNTAP.Netmask),
(ulong)tunIndex);
SetupRouteTable(mode);
}
#region Route
private void SetupRouteTable(Mode mode)
{
Global.MainForm.StatusText(i18N.Translate("Setup Route Table Rule"));
Global.Logger.Info("设置路由规则");
// Server Address
if (!IPAddress.IsLoopback(_serverAddresses))
RouteUtils.CreateRoute(_outbound.FillTemplate(_serverAddresses.ToString(), 32));
// Global Bypass IPs
RouteUtils.CreateRouteFill(_outbound, Global.Settings.TUNTAP.BypassIPs);
var tunNetworkInterface = NetworkInterfaceUtils.Get(_tun.InterfaceIndex);
switch (mode.Type)
{
case ModeType.ProxyRuleIPs:
// rules
RouteUtils.CreateRouteFill(_tun, mode.GetRules());
if (Global.Settings.TUNTAP.ProxyDNS)
{
tunNetworkInterface.SetDns(DummyDns);
// proxy dummy dns
RouteUtils.CreateRoute(_tun.FillTemplate(DummyDns, 32));
if (!Global.Settings.TUNTAP.UseCustomDNS)
// proxy AioDNS other dns
RouteUtils.CreateRoute(_tun.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.OtherDNS), 32));
}
break;
case ModeType.BypassRuleIPs:
RouteUtils.CreateRouteFill(_outbound, mode.GetRules());
tunNetworkInterface.SetDns(DummyDns);
if (!Global.Settings.TUNTAP.UseCustomDNS)
// bypass AioDNS other dns
RouteUtils.CreateRoute(_outbound.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.ChinaDNS), 32));
NetworkInterfaceUtils.SetInterfaceMetric(_tun.InterfaceIndex, 0);
RouteUtils.CreateRoute(_tun.FillTemplate("0.0.0.0", 0));
break;
}
}
private void ClearRouteTable()
{
if (!IPAddress.IsLoopback(_serverAddresses))
RouteUtils.DeleteRoute(_outbound.FillTemplate(_serverAddresses.ToString(), 32));
RouteUtils.DeleteRouteFill(_outbound, Global.Settings.TUNTAP.BypassIPs);
switch (_mode.Type)
{
case ModeType.BypassRuleIPs:
RouteUtils.DeleteRouteFill(_outbound, _mode.GetRules());
NetworkInterfaceUtils.SetInterfaceMetric(_outbound.InterfaceIndex);
break;
}
}
#endregion
public void Stop()
{
var tasks = new[]
{
Task.Run(Free),
Task.Run(ClearRouteTable),
Task.Run(_aioDnsController.Stop)
};
Task.WaitAll(tasks);
}
private void CheckDriver()
{
string binDriver = Path.Combine(Global.NetchDir, @"bin\wintun.dll");
string sysDriver = $@"{Environment.SystemDirectory}\wintun.dll";
var binHash = Utils.Utils.SHA256CheckSum(binDriver);
var sysHash = Utils.Utils.SHA256CheckSum(sysDriver);
Global.Logger.Info("自带 wintun.dll Hash: " + binHash);
Global.Logger.Info("系统 wintun.dll Hash: " + sysHash);
if (binHash == sysHash)
return;
try
{
Global.Logger.Info("Copy wintun.dll to System Directory");
File.Copy(binDriver, sysDriver, true);
}
catch (Exception e)
{
Global.Logger.Error(e.ToString());
throw new MessageException($"Failed to copy wintun.dll to system directory: {e.Message}");
}
}
}
}

View File

@@ -1,373 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
namespace Netch.Controllers
{
public class TUNTAPController : Guard, IModeController
{
private readonly List<string> _directIPs = new();
private readonly List<string> _proxyIPs = new();
/// <summary>
/// 服务器 IP 地址
/// </summary>
private IPAddress _serverAddresses;
/// <summary>
/// 本地 DNS 服务控制器
/// </summary>
public DNSController DNSController = new();
public TUNTAPController()
{
StartedKeywords.Add("Running");
StoppedKeywords.AddRange(new[] {"failed", "invalid vconfig file"});
}
public override string MainFile { get; protected set; } = "tun2socks.exe";
public override string Name { get; protected set; } = "tun2socks";
public bool Start(in Mode mode)
{
var server = MainController.Server;
// 查询服务器 IP 地址
_serverAddresses = DNS.Lookup(server.Hostname);
// 查找出口适配器
if (!Utils.Utils.SearchOutboundAdapter())
return false;
// 查找并安装 TAP 适配器
if (!SearchTapAdapter())
{
if (!AddTap())
{
Logging.Error("Tap 适配器安装失败");
return false;
}
SearchTapAdapter();
}
SetupRouteTable(mode);
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", Name));
string dns;
if (Global.Settings.TUNTAP.UseCustomDNS)
{
if (Global.Settings.TUNTAP.DNS.Any())
{
dns = DNS.Join(Global.Settings.TUNTAP.DNS);
}
else
{
Global.Settings.TUNTAP.DNS.Add("1.1.1.1");
dns = "1.1.1.1";
}
}
else
{
if (!MainController.PortCheckAndShowMessageBox(53, "DNS"))
return false;
if (!DNSController.Start())
{
Logging.Error("AioDNS 启动失败");
return false;
}
dns = "127.0.0.1";
}
var argument = new StringBuilder();
if (server is Socks5 socks5 && !socks5.Auth())
argument.Append($"-proxyServer {server.AutoResolveHostname()}:{server.Port} ");
else
argument.Append($"-proxyServer 127.0.0.1:{Global.Settings.Socks5LocalPort} ");
argument.Append(
$"-tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {dns} -tunName \"{TUNTAP.GetName(Global.TUNTAP.ComponentID)}\" ");
if (Global.Settings.TUNTAP.UseFakeDNS && Global.Flags.SupportFakeDns)
argument.Append("-fakeDns ");
return StartInstanceAuto(argument.ToString(), ProcessPriorityClass.RealTime);
}
/// <summary>
/// TUN/TAP停止
/// </summary>
public override void Stop()
{
var tasks = new[]
{
Task.Run(StopInstance),
Task.Run(ClearRouteTable),
Task.Run(DNSController.Stop)
};
Task.WaitAll(tasks);
}
/// <summary>
/// 设置绕行规则
/// </summary>
/// <returns>是否设置成功</returns>
private void SetupRouteTable(Mode mode)
{
Global.MainForm.StatusText(i18N.Translate("SetupBypass"));
Logging.Info("设置路由规则");
#region Rule IPs
switch (mode.Type)
{
case 1:
// 代理规则
Logging.Info("代理 → 规则 IP");
RouteAction(Action.Create, mode.FullRule, RouteType.TUNTAP);
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP自己记录解析了返回的 IP仅支持默认检测服务器
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
try
{
Logging.Info("代理 → STUN 服务器 IP");
RouteAction(Action.Create,
new[]
{
Dns.GetHostAddresses(Global.Settings.STUN_Server)[0],
Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0]
}.Select(ip => $"{ip}/32"),
RouteType.TUNTAP);
}
catch
{
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
}
if (Global.Settings.TUNTAP.ProxyDNS)
{
Logging.Info("代理 → 自定义 DNS");
if (Global.Settings.TUNTAP.UseCustomDNS)
RouteAction(Action.Create,
Global.Settings.TUNTAP.DNS.Select(ip => $"{ip}/32"),
RouteType.TUNTAP);
else
RouteAction(Action.Create,
new[] {"1.1.1.1", "8.8.8.8", "9.9.9.9", "185.222.222.222"}.Select(ip => $"{ip}/32"),
RouteType.TUNTAP);
}
break;
case 2:
// 绕过规则
// 将 TUN/TAP 网卡权重放到最高
Process.Start(new ProcessStartInfo
{
FileName = "netsh",
Arguments = $"interface ip set interface {Global.TUNTAP.Index} metric=0",
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true,
CreateNoWindow = true
}
);
Logging.Info("绕行 → 规则 IP");
RouteAction(Action.Create, mode.FullRule, RouteType.Outbound);
break;
}
#endregion
Logging.Info("绕行 → 服务器 IP");
if (!IPAddress.IsLoopback(_serverAddresses))
RouteAction(Action.Create, $"{_serverAddresses}/32", RouteType.Outbound);
Logging.Info("绕行 → 全局绕过 IP");
RouteAction(Action.Create, Global.Settings.BypassIPs, RouteType.Outbound);
if (mode.Type == 2)
{
// 绕过规则
Logging.Info("代理 → 全局");
RouteAction(Action.Create, "0.0.0.0/0", RouteType.TUNTAP);
}
}
/// <summary>
/// 清除绕行规则
/// </summary>
private bool ClearRouteTable()
{
RouteAction(Action.Delete, _directIPs, RouteType.Outbound);
RouteAction(Action.Delete, _proxyIPs, RouteType.TUNTAP);
_directIPs.Clear();
_proxyIPs.Clear();
return true;
}
public bool TestFakeDNS()
{
try
{
InitInstance("-h");
Instance.Start();
return Instance.StandardError.ReadToEnd().Contains("-fakeDns");
}
catch
{
return false;
}
}
/// <summary>
/// 搜索出口和TUNTAP适配器
/// </summary>
public static bool SearchTapAdapter()
{
Global.TUNTAP.Adapter = null;
Global.TUNTAP.Index = -1;
Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
// 搜索 TUN/TAP 适配器的索引
if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID))
{
Logging.Info("TAP 适配器未安装");
return false;
}
// 根据 ComponentID 寻找 Tap适配器
try
{
var adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ => _.Id == Global.TUNTAP.ComponentID);
Global.TUNTAP.Adapter = adapter;
Global.TUNTAP.Index = adapter.GetIPProperties().GetIPv4Properties().Index;
Logging.Info(
$"TAP 适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.TUNTAP.Index}");
return true;
}
catch (Exception e)
{
var msg = e switch
{
InvalidOperationException _ => $"找不到标识符为 {Global.TUNTAP.ComponentID} 的 TAP 适配器: {e.Message}",
NetworkInformationException _ => $"获取 Tap 适配器信息错误: {e.Message}",
_ => $"Tap 适配器其他异常: {e}"
};
Logging.Error(msg);
return false;
}
}
private static bool AddTap()
{
TUNTAP.addtap();
// 给点时间不然立马安装完毕就查找适配器可能会导致找不到适配器ID
Thread.Sleep(1000);
if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID = TUNTAP.GetComponentID()))
{
Logging.Error("找不到 TAP 适配器,驱动可能安装失败");
return false;
}
return true;
}
private void RouteAction(Action action, in IEnumerable<string> ipNetworks, RouteType routeType,
int metric = 0)
{
foreach (var address in ipNetworks)
RouteAction(action, address, routeType, metric);
}
private bool RouteAction(Action action, in string ipNetwork, RouteType routeType, int metric = 0)
{
string gateway;
int index;
switch (routeType)
{
case RouteType.Outbound:
gateway = Global.Outbound.Gateway.ToString();
index = Global.Outbound.Index;
break;
case RouteType.TUNTAP:
gateway = Global.Settings.TUNTAP.Gateway;
index = Global.TUNTAP.Index;
break;
default:
throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null);
}
string network;
ushort cidr;
try
{
var s = ipNetwork.Split('/');
network = s[0];
cidr = ushort.Parse(s[1]);
}
catch
{
Logging.Warning($"Failed to parse rule {ipNetwork}");
return false;
}
bool result;
switch (action)
{
case Action.Create:
{
result = NativeMethods.CreateRoute(network, cidr, gateway, index, metric);
switch (routeType)
{
case RouteType.Outbound:
_directIPs.Add(ipNetwork);
break;
case RouteType.TUNTAP:
_proxyIPs.Add(ipNetwork);
break;
}
break;
}
case Action.Delete:
result = NativeMethods.DeleteRoute(network, cidr, gateway, index, metric);
break;
default:
throw new ArgumentOutOfRangeException(nameof(action), action, null);
}
if (!result)
Logging.Warning($"Failed to {action} Route on {routeType} Adapter: {ipNetwork} metric {metric}");
return result;
}
private enum RouteType
{
Outbound,
TUNTAP
}
private enum Action
{
Create,
Delete
}
}
}

View File

@@ -1,13 +1,13 @@
using System;
using Netch.Models.GitHubRelease;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Netch.Models.GitHubRelease;
using Netch.Utils;
using Newtonsoft.Json;
namespace Netch.Controllers
{
@@ -17,22 +17,26 @@ namespace Netch.Controllers
public const string Repo = @"Netch";
public const string Name = @"Netch";
public const string Copyright = @"Copyright © 2019 - 2020";
public const string Copyright = @"Copyright © 2019 - 2021";
public const string AssemblyVersion = @"1.7.2";
public const string AssemblyVersion = @"1.8.5";
private const string Suffix = @"";
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
public static string LatestVersionNumber;
public static string LatestVersionUrl;
public static Release LatestRelease;
public static Release LatestRelease = null!;
public static event EventHandler NewVersionFound;
public static event EventHandler NewVersionFoundFailed;
public static event EventHandler NewVersionNotFound;
public static string LatestVersionNumber => LatestRelease.tag_name;
public static async void Check(bool isPreRelease)
public static string LatestVersionUrl => LatestRelease.html_url;
public static event EventHandler? NewVersionFound;
public static event EventHandler? NewVersionFoundFailed;
public static event EventHandler? NewVersionNotFound;
public static async Task Check(bool isPreRelease)
{
try
{
@@ -41,88 +45,73 @@ namespace Netch.Controllers
var json = await WebUtil.DownloadStringAsync(WebUtil.CreateRequest(url));
var releases = JsonConvert.DeserializeObject<List<Release>>(json);
LatestRelease = VersionUtil.GetLatestRelease(releases, isPreRelease);
LatestVersionNumber = LatestRelease.tag_name;
LatestVersionUrl = LatestRelease.html_url;
Logging.Info($"Github 最新发布版本: {LatestRelease.tag_name}");
var releases = JsonSerializer.Deserialize<List<Release>>(json)!;
LatestRelease = GetLatestRelease(releases, isPreRelease);
Global.Logger.Info($"Github 最新发布版本: {LatestRelease.tag_name}");
if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0)
{
Logging.Info("发现新版本");
Global.Logger.Info("发现新版本");
NewVersionFound?.Invoke(null, new EventArgs());
}
else
{
Logging.Info("目前是最新版本");
Global.Logger.Info("目前是最新版本");
NewVersionNotFound?.Invoke(null, new EventArgs());
}
}
catch (Exception e)
{
if (e is WebException)
Logging.Warning($"获取新版本失败: {e.Message}");
Global.Logger.Warning($"获取新版本失败: {e.Message}");
else
Logging.Warning(e.ToString());
Global.Logger.Warning(e.ToString());
NewVersionFoundFailed?.Invoke(null, new EventArgs());
}
}
public static async Task UpdateNetch(DownloadProgressChangedEventHandler onDownloadProgressChanged)
public static void GetLatestUpdateFileNameAndHash(out string fileName, out string sha256, string? keyword = null)
{
using WebClient client = new();
fileName = string.Empty;
sha256 = string.Empty;
var latestVersionDownloadUrl = LatestRelease.assets[0].browser_download_url;
var tagPage = await client.DownloadStringTaskAsync(LatestVersionUrl);
var match = Regex.Match(tagPage, @"<td .*>(?<sha256>.*)</td>", RegexOptions.Singleline);
var matches = Regex.Matches(LatestRelease.body, @"^\| (?<filename>.*) \| (?<sha256>.*) \|\r?$", RegexOptions.Multiline)
.Cast<Match>()
.Skip(2);
/*
Skip(2)
| 文件名 | SHA256 |
| :- | :- |
*/
// TODO Replace with regex get basename and sha256
var fileName = Path.GetFileName(new Uri(latestVersionDownloadUrl).LocalPath);
fileName = fileName.Insert(fileName.LastIndexOf('.'), LatestVersionNumber);
var fileFullPath = Path.Combine(Global.NetchDir, "data", fileName);
Match match = keyword == null ? matches.First() : matches.First(m => m.Groups["filename"].Value.Contains(keyword));
var sha256 = match.Groups["sha256"].Value;
fileName = match.Groups["filename"].Value;
sha256 = match.Groups["sha256"].Value;
}
if (File.Exists(fileFullPath))
public static string GetLatestReleaseContent()
{
var sb = new StringBuilder();
foreach (string l in LatestRelease.body.GetLines(false).SkipWhile(l => l.FirstOrDefault() != '#'))
{
if (Utils.Utils.SHA256CheckSum(fileFullPath) == sha256)
{
RunUpdater();
return;
}
if (l.Contains("校验和"))
break;
File.Delete(fileFullPath);
sb.AppendLine(l);
}
try
{
client.DownloadProgressChanged += onDownloadProgressChanged;
await client.DownloadFileTaskAsync(new Uri(latestVersionDownloadUrl), fileFullPath);
client.DownloadProgressChanged -= onDownloadProgressChanged;
}
catch (Exception e)
{
throw new Exception(i18N.Translate("Download Update Failed", ": ") + e.Message);
}
return sb.ToString();
}
if (Utils.Utils.SHA256CheckSum(fileFullPath) != sha256)
throw new Exception(i18N.Translate("The downloaded file has the wrong hash"));
public static Release GetLatestRelease(IEnumerable<Release> releases, bool isPreRelease)
{
if (!isPreRelease)
releases = releases.Where(release => !release.prerelease);
RunUpdater();
void RunUpdater()
{
// if debugging process stopped, debugger will kill child processes!!!!
// 调试进程结束,调试器将会杀死子进程
// uncomment if(!Debugger.isAttach) block in NetchUpdater Project's main() method and attach to NetchUpdater process to debug
// 在 NetchUpdater 项目的 main() 方法中取消注释 if!Debugger.isAttach并附加到 NetchUpdater 进程进行调试
Process.Start(new ProcessStartInfo
{
FileName = Path.Combine(Global.NetchDir, "NetchUpdater.exe"),
Arguments =
$"{Global.Settings.UDPSocketPort} \"{fileFullPath}\" \"{Global.NetchDir}\""
});
}
var ordered = releases.OrderByDescending(release => release.tag_name, new VersionUtil.VersionComparer());
return ordered.ElementAt(0);
}
}
}

10
Netch/Enums/Modes.cs Normal file
View File

@@ -0,0 +1,10 @@
namespace Netch.Enums
{
public enum ModeType
{
Process = 0,
ProxyRuleIPs = 1,
BypassRuleIPs = 2,
Pcap2Socks = 6
}
}

11
Netch/Flags.cs Normal file
View File

@@ -0,0 +1,11 @@
using System;
namespace Netch
{
public static class Flags
{
public static readonly bool IsWindows10Upper = Environment.OSVersion.Version.Major >= 10;
public static bool AlwaysShowNewVersionFound { get; set; }
}
}

View File

@@ -93,7 +93,6 @@
this.Controls.Add(this.NetchPictureBox);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.Name = "AboutForm";

View File

@@ -1,7 +1,8 @@
using System;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Diagnostics;
using System.Windows.Forms;
using Netch.Utils;
namespace Netch.Forms
{
@@ -10,6 +11,7 @@ namespace Netch.Forms
public AboutForm()
{
InitializeComponent();
Icon = Resources.icon;
}
private void AboutForm_Load(object sender, EventArgs e)
@@ -19,17 +21,17 @@ namespace Netch.Forms
private void NetchPictureBox_Click(object sender, EventArgs e)
{
Process.Start("https://github.com/NetchX/Netch");
Utils.Utils.Open("https://github.com/NetchX/Netch");
}
private void ChannelLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Process.Start("https://t.me/Netch");
Utils.Utils.Open("https://t.me/Netch");
}
private void SponsorPictureBox_Click(object sender, EventArgs e)
{
Process.Start("https://www.mansora.co");
Utils.Utils.Open("https://www.mansora.co");
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -119,7 +119,6 @@
this.Controls.Add(this.IPGroupBox);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.Name = "GlobalBypassIPForm";

View File

@@ -1,7 +1,9 @@
using System;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using Netch.Utils;
namespace Netch.Forms
{
@@ -10,18 +12,18 @@ namespace Netch.Forms
public GlobalBypassIPForm()
{
InitializeComponent();
Icon = Resources.icon;
}
private void GlobalBypassIPForm_Load(object sender, EventArgs e)
{
i18N.TranslateForm(this);
IPListBox.Items.AddRange(Global.Settings.BypassIPs.ToArray());
IPListBox.Items.AddRange(Global.Settings.TUNTAP.BypassIPs.Cast<object>().ToArray());
for (var i = 32; i >= 1; i--)
{
PrefixComboBox.Items.Add(i);
}
PrefixComboBox.SelectedIndex = 0;
}
@@ -30,13 +32,9 @@ namespace Netch.Forms
if (!string.IsNullOrEmpty(IPTextBox.Text))
{
if (IPAddress.TryParse(IPTextBox.Text, out var address))
{
IPListBox.Items.Add(string.Format("{0}/{1}", address, PrefixComboBox.SelectedItem));
}
IPListBox.Items.Add($"{address}/{PrefixComboBox.SelectedItem}");
else
{
MessageBoxX.Show(i18N.Translate("Please enter a correct IP address"));
}
}
else
{
@@ -47,26 +45,20 @@ namespace Netch.Forms
private void DeleteButton_Click(object sender, EventArgs e)
{
if (IPListBox.SelectedIndex != -1)
{
IPListBox.Items.RemoveAt(IPListBox.SelectedIndex);
}
else
{
MessageBoxX.Show(i18N.Translate("Please select an IP"));
}
}
private void ControlButton_Click(object sender, EventArgs e)
{
Global.Settings.BypassIPs.Clear();
Global.Settings.TUNTAP.BypassIPs.Clear();
foreach (var ip in IPListBox.Items)
{
Global.Settings.BypassIPs.Add(ip as string);
}
Global.Settings.TUNTAP.BypassIPs.Add((string)ip);
Configuration.Save();
MessageBoxX.Show(i18N.Translate("Saved"));
Close();
}
}
}
}

File diff suppressed because it is too large Load Diff

88
Netch/Forms/LogForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,88 @@
using System.ComponentModel;
namespace Netch.Forms
{
partial class LogForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.SuspendLayout();
//
// richTextBox1
//
this.richTextBox1.BackColor = System.Drawing.SystemColors.Control;
this.richTextBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Top;
this.richTextBox1.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.richTextBox1.Location = new System.Drawing.Point(0, 0);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.ReadOnly = true;
this.richTextBox1.Size = new System.Drawing.Size(454, 288);
this.richTextBox1.TabIndex = 0;
this.richTextBox1.Text = "";
this.richTextBox1.TextChanged += new System.EventHandler(this.richTextBox1_TextChanged);
//
// checkBox1
//
this.checkBox1.AutoSize = true;
this.checkBox1.Location = new System.Drawing.Point(12, 297);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(101, 21);
this.checkBox1.TabIndex = 1;
this.checkBox1.Text = "Scroll to End";
this.checkBox1.UseVisualStyleBackColor = true;
//
// LogForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(454, 318);
this.ControlBox = false;
this.Controls.Add(this.checkBox1);
this.Controls.Add(this.richTextBox1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "LogForm";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.Text = "LogForm";
this.Load += new System.EventHandler(this.Notifycation_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.CheckBox checkBox1;
public System.Windows.Forms.RichTextBox richTextBox1;
}
}

78
Netch/Forms/LogForm.cs Normal file
View File

@@ -0,0 +1,78 @@
using System;
using System.ComponentModel;
using System.Windows.Forms;
using Vanara.PInvoke;
using static Vanara.PInvoke.User32;
namespace Netch.Forms
{
public partial class LogForm : Form
{
private readonly Form _parent;
public LogForm(Form parent)
{
InitializeComponent();
_parent = parent;
}
protected override void OnLoad(EventArgs? e)
{
base.OnLoad(e);
Parent_Move(null!, null!);
}
private void Parent_Move(object? sender, EventArgs? e)
{
var cl = Location;
var fl = _parent.Location;
cl.X = fl.X + _parent.Width;
cl.Y = fl.Y;
Location = cl;
}
private void Parent_Activated(object? sender, EventArgs? e)
{
SetWindowPos(Handle,
HWND.HWND_TOPMOST,
0,
0,
0,
0,
SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_SHOWWINDOW);
SetWindowPos(Handle,
HWND.HWND_NOTOPMOST,
0,
0,
0,
0,
SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_SHOWWINDOW);
}
private void richTextBox1_TextChanged(object? sender, EventArgs? e)
{
if (!checkBox1.Checked)
return;
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}
private void Notifycation_Load(object? sender, EventArgs? e)
{
_parent.LocationChanged += Parent_Move;
_parent.SizeChanged += Parent_Move;
_parent.Activated += Parent_Activated;
}
protected override void OnClosing(CancelEventArgs? e)
{
_parent.Activated -= Parent_Activated;
_parent.LocationChanged -= Parent_Move;
_parent.SizeChanged -= Parent_Move;
base.OnClosing(e!);
}
}
}

60
Netch/Forms/LogForm.resx Normal file
View File

@@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -29,24 +29,21 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.MenuStrip = new System.Windows.Forms.MenuStrip();
this.ServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ImportServersFromClipboardToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CreateProcessModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ReloadModesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CreateRouteTableRuleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ManageSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UpdateServersFromSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.OptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.OpenDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CleanDNSCacheToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UpdateACLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.updateACLWithProxyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UninstallServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UninstallTapDriverToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.removeNetchFirewallRulesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowHideConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.HelpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CheckForUpdatesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.fAQToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -60,7 +57,7 @@
this.ModeLabel = new System.Windows.Forms.Label();
this.ServerLabel = new System.Windows.Forms.Label();
this.ProfileNameText = new System.Windows.Forms.TextBox();
this.ModeComboBox = new System.Windows.Forms.SearchComboBox();
this.ModeComboBox = new System.Windows.Forms.ComboBox();
this.ServerComboBox = new System.Windows.Forms.ComboBox();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.EditServerPictureBox = new System.Windows.Forms.PictureBox();
@@ -88,7 +85,6 @@
this.ProfileTable = new System.Windows.Forms.TableLayoutPanel();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.ButtomControlContainerControl = new System.Windows.Forms.ContainerControl();
this.updatePACToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MenuStrip.SuspendLayout();
this.ConfigurationGroupBox.SuspendLayout();
this.configLayoutPanel.SuspendLayout();
@@ -147,7 +143,7 @@
//
this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.CreateProcessModeToolStripMenuItem,
this.ReloadModesToolStripMenuItem});
this.CreateRouteTableRuleToolStripMenuItem});
this.ModeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.ModeToolStripMenuItem.Name = "ModeToolStripMenuItem";
this.ModeToolStripMenuItem.Size = new System.Drawing.Size(55, 21);
@@ -156,23 +152,22 @@
// CreateProcessModeToolStripMenuItem
//
this.CreateProcessModeToolStripMenuItem.Name = "CreateProcessModeToolStripMenuItem";
this.CreateProcessModeToolStripMenuItem.Size = new System.Drawing.Size(202, 22);
this.CreateProcessModeToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.CreateProcessModeToolStripMenuItem.Text = "Create Process Mode";
this.CreateProcessModeToolStripMenuItem.Click += new System.EventHandler(this.CreateProcessModeToolStripButton_Click);
//
// ReloadModesToolStripMenuItem
// CreateRouteTableRuleToolStripMenuItem
//
this.ReloadModesToolStripMenuItem.Name = "ReloadModesToolStripMenuItem";
this.ReloadModesToolStripMenuItem.Size = new System.Drawing.Size(202, 22);
this.ReloadModesToolStripMenuItem.Text = "Reload Modes";
this.ReloadModesToolStripMenuItem.Click += new System.EventHandler(this.ReloadModesToolStripMenuItem_Click);
this.CreateRouteTableRuleToolStripMenuItem.Name = "CreateRouteTableRuleToolStripMenuItem";
this.CreateRouteTableRuleToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.CreateRouteTableRuleToolStripMenuItem.Text = "Create Route Table Rule";
this.CreateRouteTableRuleToolStripMenuItem.Click += new System.EventHandler(this.createRouteTableModeToolStripMenuItem_Click);
//
// SubscribeToolStripMenuItem
//
this.SubscribeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.ManageSubscribeLinksToolStripMenuItem,
this.UpdateServersFromSubscribeLinksToolStripMenuItem,
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem});
this.UpdateServersFromSubscribeLinksToolStripMenuItem});
this.SubscribeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.SubscribeToolStripMenuItem.Name = "SubscribeToolStripMenuItem";
this.SubscribeToolStripMenuItem.Size = new System.Drawing.Size(77, 21);
@@ -192,23 +187,14 @@
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Text = "Update Servers From Subscribe Links";
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscribeLinksToolStripMenuItem_Click);
//
// UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem
//
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Name = "UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem";
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Size = new System.Drawing.Size(294, 22);
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Text = "Update Servers From Subscribe Links With Proxy";
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem_Click);
//
// OptionsToolStripMenuItem
//
this.OptionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.OpenDirectoryToolStripMenuItem,
this.ShowHideConsoleToolStripMenuItem,
this.CleanDNSCacheToolStripMenuItem,
this.UpdateACLToolStripMenuItem,
this.updateACLWithProxyToolStripMenuItem,
this.updatePACToolStripMenuItem,
this.UninstallServiceToolStripMenuItem,
this.UninstallTapDriverToolStripMenuItem});
this.removeNetchFirewallRulesToolStripMenuItem});
this.OptionsToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.OptionsToolStripMenuItem.Name = "OptionsToolStripMenuItem";
this.OptionsToolStripMenuItem.Size = new System.Drawing.Size(66, 21);
@@ -217,44 +203,37 @@
// OpenDirectoryToolStripMenuItem
//
this.OpenDirectoryToolStripMenuItem.Name = "OpenDirectoryToolStripMenuItem";
this.OpenDirectoryToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.OpenDirectoryToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.OpenDirectoryToolStripMenuItem.Text = "Open Directory";
this.OpenDirectoryToolStripMenuItem.Click += new System.EventHandler(this.OpenDirectoryToolStripMenuItem_Click);
//
// CleanDNSCacheToolStripMenuItem
//
this.CleanDNSCacheToolStripMenuItem.Name = "CleanDNSCacheToolStripMenuItem";
this.CleanDNSCacheToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.CleanDNSCacheToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.CleanDNSCacheToolStripMenuItem.Text = "Clean DNS Cache";
this.CleanDNSCacheToolStripMenuItem.Click += new System.EventHandler(this.CleanDNSCacheToolStripMenuItem_Click);
//
// UpdateACLToolStripMenuItem
//
this.UpdateACLToolStripMenuItem.Name = "UpdateACLToolStripMenuItem";
this.UpdateACLToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.UpdateACLToolStripMenuItem.Text = "Update ACL";
this.UpdateACLToolStripMenuItem.Click += new System.EventHandler(this.updateACLToolStripMenuItem_Click);
//
// updateACLWithProxyToolStripMenuItem
//
this.updateACLWithProxyToolStripMenuItem.Name = "updateACLWithProxyToolStripMenuItem";
this.updateACLWithProxyToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.updateACLWithProxyToolStripMenuItem.Text = "Update ACL with proxy";
this.updateACLWithProxyToolStripMenuItem.Click += new System.EventHandler(this.updateACLWithProxyToolStripMenuItem_Click);
//
// UninstallServiceToolStripMenuItem
//
this.UninstallServiceToolStripMenuItem.Name = "UninstallServiceToolStripMenuItem";
this.UninstallServiceToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.UninstallServiceToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.UninstallServiceToolStripMenuItem.Text = "Uninstall NF Service";
this.UninstallServiceToolStripMenuItem.Click += new System.EventHandler(this.UninstallServiceToolStripMenuItem_Click);
//
// UninstallTapDriverToolStripMenuItem
// removeNetchFirewallRulesToolStripMenuItem
//
this.UninstallTapDriverToolStripMenuItem.Name = "UninstallTapDriverToolStripMenuItem";
this.UninstallTapDriverToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.UninstallTapDriverToolStripMenuItem.Text = "Uninstall TUN/TAP driver";
this.UninstallTapDriverToolStripMenuItem.Click += new System.EventHandler(this.UninstallTapDriverToolStripMenuItem_Click);
this.removeNetchFirewallRulesToolStripMenuItem.Name = "removeNetchFirewallRulesToolStripMenuItem";
this.removeNetchFirewallRulesToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.removeNetchFirewallRulesToolStripMenuItem.Text = "Remove Netch Firewall Rules";
this.removeNetchFirewallRulesToolStripMenuItem.Click += new System.EventHandler(this.RemoveNetchFirewallRulesToolStripMenuItem_Click);
//
// ShowHideConsoleToolStripMenuItem
//
this.ShowHideConsoleToolStripMenuItem.Name = "ShowHideConsoleToolStripMenuItem";
this.ShowHideConsoleToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.ShowHideConsoleToolStripMenuItem.Text = "Show/Hide Console";
this.ShowHideConsoleToolStripMenuItem.Click += new System.EventHandler(this.ShowHideConsoleToolStripMenuItem_Click);
//
// HelpToolStripMenuItem
//
@@ -399,9 +378,9 @@
//
// ModeComboBox
//
this.ModeComboBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
this.ModeComboBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ModeComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.ModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.ModeComboBox.FormattingEnabled = true;
this.ModeComboBox.IntegralHeight = false;
this.ModeComboBox.Location = new System.Drawing.Point(54, 33);
@@ -409,7 +388,7 @@
this.ModeComboBox.Size = new System.Drawing.Size(546, 24);
this.ModeComboBox.TabIndex = 2;
this.ModeComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
this.ModeComboBox.SelectedIndexChanged += new System.EventHandler(this.ModeComboBox_SelectedIndexChanged);
this.ModeComboBox.SelectionChangeCommitted += new System.EventHandler(this.ModeComboBox_SelectionChangeCommitted);
//
// ServerComboBox
//
@@ -424,7 +403,7 @@
this.ServerComboBox.Size = new System.Drawing.Size(546, 24);
this.ServerComboBox.TabIndex = 1;
this.ServerComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
this.ServerComboBox.SelectedIndexChanged += new System.EventHandler(this.ServerComboBox_SelectedIndexChanged);
this.ServerComboBox.SelectionChangeCommitted += new System.EventHandler(this.ServerComboBox_SelectionChangeCommitted);
//
// tableLayoutPanel2
//
@@ -618,7 +597,6 @@
// NotifyIcon
//
this.NotifyIcon.ContextMenuStrip = this.NotifyMenu;
this.NotifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("NotifyIcon.Icon")));
this.NotifyIcon.Text = "Netch";
this.NotifyIcon.Visible = true;
this.NotifyIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.NotifyIcon_MouseDoubleClick);
@@ -708,13 +686,6 @@
this.ButtomControlContainerControl.TabStop = false;
this.ButtomControlContainerControl.Text = "groupBox1";
//
// updatePACToolStripMenuItem
//
this.updatePACToolStripMenuItem.Name = "updatePACToolStripMenuItem";
this.updatePACToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.updatePACToolStripMenuItem.Text = "Update PAC";
this.updatePACToolStripMenuItem.Click += new System.EventHandler(this.updatePACToolStripMenuItem_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -725,9 +696,8 @@
this.Controls.Add(this.MenuStrip);
this.Controls.Add(this.StatusStrip);
this.Controls.Add(this.flowLayoutPanel1);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.Name = "MainForm";
@@ -761,6 +731,10 @@
}
private System.Windows.Forms.ToolStripMenuItem CreateRouteTableRuleToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem removeNetchFirewallRulesToolStripMenuItem;
private System.Windows.Forms.ToolStripButton AboutToolStripButton;
private System.Windows.Forms.ToolStripMenuItem CleanDNSCacheToolStripMenuItem;
private System.Windows.Forms.TableLayoutPanel configLayoutPanel;
@@ -778,7 +752,7 @@
private System.Windows.Forms.ToolStripMenuItem ImportServersFromClipboardToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ManageSubscribeLinksToolStripMenuItem;
private System.Windows.Forms.MenuStrip MenuStrip;
private System.Windows.Forms.SearchComboBox ModeComboBox;
private System.Windows.Forms.ComboBox ModeComboBox;
private System.Windows.Forms.Label ModeLabel;
private System.Windows.Forms.ToolStripMenuItem ModeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem HelpToolStripMenuItem;
@@ -791,9 +765,7 @@
private System.Windows.Forms.Label ProfileLabel;
private System.Windows.Forms.TextBox ProfileNameText;
private System.Windows.Forms.TableLayoutPanel ProfileTable;
private System.Windows.Forms.ToolStripMenuItem UninstallTapDriverToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem CheckForUpdatesToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ReloadModesToolStripMenuItem;
private System.Windows.Forms.ComboBox ServerComboBox;
private System.Windows.Forms.Label ServerLabel;
private System.Windows.Forms.ToolStripMenuItem ServerToolStripMenuItem;
@@ -806,10 +778,7 @@
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.ToolStripMenuItem UninstallServiceToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem UpdateACLToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem updateACLWithProxyToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem;
private System.Windows.Forms.ToolStripStatusLabel UploadSpeedLabel;
private System.Windows.Forms.ToolStripStatusLabel UsedBandwidthLabel;
private System.Windows.Forms.ToolStripLabel NewVersionLabel;
@@ -822,6 +791,6 @@
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.ContainerControl ButtomControlContainerControl;
private System.Windows.Forms.ToolStripMenuItem updatePACToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ShowHideConsoleToolStripMenuItem;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
using System;
using System.Windows.Forms;
using Netch.Models;
using Netch.Models;
using Netch.Utils;
using System;
using System.Windows.Forms;
namespace Netch.Forms
{
@@ -14,7 +14,11 @@ namespace Netch.Forms
/// <param name="level">弹窗等级 (标题, 图标)</param>
/// <param name="confirm">需要确认</param>
/// <param name="owner">阻止 owner Focus() 直到 Messageox 被关闭</param>
public static DialogResult Show(string text, LogLevel level = LogLevel.INFO, string title = "", bool confirm = false, IWin32Window owner = null)
public static DialogResult Show(string text,
LogLevel level = LogLevel.INFO,
string title = "",
bool confirm = false,
IWin32Window? owner = null)
{
MessageBoxIcon msgIcon;
if (string.IsNullOrWhiteSpace(title))
@@ -34,12 +38,7 @@ namespace Netch.Forms
_ => 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

@@ -0,0 +1,27 @@
using System.IO;
using System.Text;
namespace Netch.Forms.Mode
{
public static class ModeEditorUtils
{
public static string ToSafeFileName(string text)
{
var fileName = new StringBuilder(text);
foreach (var c in Path.GetInvalidFileNameChars())
fileName.Replace(c, '_');
return fileName.ToString();
}
public static string GetCustomModeRelativePath(string name)
{
if (name == string.Empty)
return string.Empty;
var safeFileName = ToSafeFileName(name);
var relativePath = $"Custom\\{safeFileName}.txt";
return relativePath;
}
}
}

View File

@@ -31,129 +31,40 @@ namespace Netch.Forms.Mode
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Process));
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
this.UseCustomFilenameBox = new System.Windows.Forms.CheckBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.FilenameLabel = new System.Windows.Forms.Label();
this.FilenameTextBox = new System.Windows.Forms.TextBox();
this.ScanButton = new System.Windows.Forms.Button();
this.ProcessGroupBox = new System.Windows.Forms.GroupBox();
this.AddButton = new System.Windows.Forms.Button();
this.ProcessNameTextBox = new System.Windows.Forms.TextBox();
this.RuleListBox = new System.Windows.Forms.ListBox();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.ControlButton = new System.Windows.Forms.Button();
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.containerControl1 = new System.Windows.Forms.ContainerControl();
this.RuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.ProcessGroupBox = new System.Windows.Forms.GroupBox();
this.SelectButton = new System.Windows.Forms.Button();
this.ScanButton = new System.Windows.Forms.Button();
this.ValidationButton = new System.Windows.Forms.Button();
this.ControlButton = new System.Windows.Forms.Button();
this.ConfigurationGroupBox.SuspendLayout();
this.ProcessGroupBox.SuspendLayout();
this.contextMenuStrip.SuspendLayout();
this.containerControl1.SuspendLayout();
this.ProcessGroupBox.SuspendLayout();
this.SuspendLayout();
//
// ConfigurationGroupBox
//
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
this.ConfigurationGroupBox.Controls.Add(this.UseCustomFilenameBox);
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
this.ConfigurationGroupBox.Controls.Add(this.FilenameLabel);
this.ConfigurationGroupBox.Controls.Add(this.FilenameTextBox);
this.ConfigurationGroupBox.Controls.Add(this.ScanButton);
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
this.ConfigurationGroupBox.Controls.Add(this.ProcessGroupBox);
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
this.ConfigurationGroupBox.Location = new System.Drawing.Point(12, 12);
this.ConfigurationGroupBox.Controls.Add(this.ControlButton);
this.ConfigurationGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ConfigurationGroupBox.Location = new System.Drawing.Point(12, 5);
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
this.ConfigurationGroupBox.Size = new System.Drawing.Size(340, 344);
this.ConfigurationGroupBox.Size = new System.Drawing.Size(431, 378);
this.ConfigurationGroupBox.TabIndex = 0;
this.ConfigurationGroupBox.TabStop = false;
this.ConfigurationGroupBox.Text = "Configuration";
//
// UseCustomFilenameBox
//
this.UseCustomFilenameBox.AutoSize = true;
this.UseCustomFilenameBox.Location = new System.Drawing.Point(84, 76);
this.UseCustomFilenameBox.Name = "UseCustomFilenameBox";
this.UseCustomFilenameBox.Size = new System.Drawing.Size(152, 21);
this.UseCustomFilenameBox.TabIndex = 9;
this.UseCustomFilenameBox.Text = "Use Custom Filename";
this.UseCustomFilenameBox.UseVisualStyleBackColor = true;
this.UseCustomFilenameBox.CheckedChanged += new System.EventHandler(this.UseCustomFilenameBox_CheckedChanged);
//
// FilenameLabel
//
this.FilenameLabel.AutoSize = true;
this.FilenameLabel.Location = new System.Drawing.Point(12, 55);
this.FilenameLabel.Name = "FilenameLabel";
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
this.FilenameLabel.TabIndex = 6;
this.FilenameLabel.Text = "Filename";
//
// FilenameTextBox
//
this.FilenameTextBox.Location = new System.Drawing.Point(84, 52);
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.Size = new System.Drawing.Size(250, 23);
this.FilenameTextBox.TabIndex = 5;
//
// ScanButton
//
this.ScanButton.Location = new System.Drawing.Point(6, 315);
this.ScanButton.Name = "ScanButton";
this.ScanButton.Size = new System.Drawing.Size(75, 23);
this.ScanButton.TabIndex = 4;
this.ScanButton.Text = "Scan";
this.ScanButton.UseVisualStyleBackColor = true;
this.ScanButton.Click += new System.EventHandler(this.ScanButton_Click);
//
// ProcessGroupBox
//
this.ProcessGroupBox.Controls.Add(this.AddButton);
this.ProcessGroupBox.Controls.Add(this.ProcessNameTextBox);
this.ProcessGroupBox.Location = new System.Drawing.Point(6, 263);
this.ProcessGroupBox.Name = "ProcessGroupBox";
this.ProcessGroupBox.Size = new System.Drawing.Size(328, 46);
this.ProcessGroupBox.TabIndex = 3;
this.ProcessGroupBox.TabStop = false;
//
// AddButton
//
this.AddButton.Location = new System.Drawing.Point(247, 15);
this.AddButton.Name = "AddButton";
this.AddButton.Size = new System.Drawing.Size(75, 23);
this.AddButton.TabIndex = 1;
this.AddButton.Text = "Add";
this.AddButton.UseVisualStyleBackColor = true;
this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
//
// ProcessNameTextBox
//
this.ProcessNameTextBox.Location = new System.Drawing.Point(6, 15);
this.ProcessNameTextBox.Name = "ProcessNameTextBox";
this.ProcessNameTextBox.Size = new System.Drawing.Size(222, 23);
this.ProcessNameTextBox.TabIndex = 0;
//
// RuleListBox
//
this.RuleListBox.FormattingEnabled = true;
this.RuleListBox.Dock = DockStyle.Fill;
this.RuleListBox.ItemHeight = 17;
this.RuleListBox.Location = new System.Drawing.Point(0, 0);
this.RuleListBox.Name = "RuleListBox";
this.RuleListBox.Size = new System.Drawing.Size(328, 157);
this.RuleListBox.TabIndex = 2;
this.RuleListBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.RuleListBox_MouseUp);
//
// RemarkTextBox
//
this.RemarkTextBox.Location = new System.Drawing.Point(84, 22);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(250, 23);
this.RemarkTextBox.TabIndex = 1;
this.RemarkTextBox.TextChanged += new System.EventHandler(this.RemarkTextBox_TextChanged);
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
@@ -163,80 +74,138 @@ namespace Netch.Forms.Mode
this.RemarkLabel.TabIndex = 0;
this.RemarkLabel.Text = "Remark";
//
// contextMenuStrip
// RemarkTextBox
//
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {this.DeleteToolStripMenuItem});
this.contextMenuStrip.Name = "contextMenuStrip";
this.contextMenuStrip.Size = new System.Drawing.Size(153, 48);
this.RemarkTextBox.Location = new System.Drawing.Point(84, 22);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(341, 23);
this.RemarkTextBox.TabIndex = 1;
this.RemarkTextBox.TextChanged += new System.EventHandler(this.RemarkTextBox_TextChanged);
//
// ControlButton
// FilenameLabel
//
this.ControlButton.Location = new System.Drawing.Point(277, 362);
this.ControlButton.Name = "ControlButton";
this.ControlButton.Size = new System.Drawing.Size(75, 23);
this.ControlButton.TabIndex = 1;
this.ControlButton.Text = "Save";
this.ControlButton.UseVisualStyleBackColor = true;
this.ControlButton.Click += new System.EventHandler(this.ControlButton_Click);
this.FilenameLabel.AutoSize = true;
this.FilenameLabel.Location = new System.Drawing.Point(12, 55);
this.FilenameLabel.Name = "FilenameLabel";
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
this.FilenameLabel.TabIndex = 2;
this.FilenameLabel.Text = "Filename";
//
// DeleteToolStripMenuItem
// FilenameTextBox
//
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.DeleteToolStripMenuItem.Text = "Delete";
this.DeleteToolStripMenuItem.Click += new System.EventHandler(this.deleteRule_Click);
this.FilenameTextBox.Location = new System.Drawing.Point(84, 52);
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.ReadOnly = true;
this.FilenameTextBox.Size = new System.Drawing.Size(341, 23);
this.FilenameTextBox.TabIndex = 3;
//
// containerControl1
//
this.containerControl1.Controls.Add(this.RuleListBox);
this.containerControl1.Location = new System.Drawing.Point(6, 100);
this.containerControl1.Controls.Add(this.RuleRichTextBox);
this.containerControl1.Location = new System.Drawing.Point(6, 81);
this.containerControl1.Name = "containerControl1";
this.containerControl1.Size = new System.Drawing.Size(328, 157);
this.containerControl1.TabIndex = 10;
this.containerControl1.Padding = new Padding(0);
this.containerControl1.Size = new System.Drawing.Size(419, 221);
this.containerControl1.TabIndex = 4;
this.containerControl1.Text = "containerControl1";
//
// RuleRichTextBox
//
this.RuleRichTextBox.DetectUrls = false;
this.RuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.RuleRichTextBox.Location = new System.Drawing.Point(0, 0);
this.RuleRichTextBox.Name = "RuleRichTextBox";
this.RuleRichTextBox.Size = new System.Drawing.Size(419, 221);
this.RuleRichTextBox.TabIndex = 0;
this.RuleRichTextBox.Text = "";
this.RuleRichTextBox.WordWrap = false;
//
// ProcessGroupBox
//
this.ProcessGroupBox.Controls.Add(this.SelectButton);
this.ProcessGroupBox.Controls.Add(this.ScanButton);
this.ProcessGroupBox.Controls.Add(this.ValidationButton);
this.ProcessGroupBox.Location = new System.Drawing.Point(6, 295);
this.ProcessGroupBox.Name = "ProcessGroupBox";
this.ProcessGroupBox.Size = new System.Drawing.Size(419, 44);
this.ProcessGroupBox.TabIndex = 5;
this.ProcessGroupBox.TabStop = false;
//
// SelectButton
//
this.SelectButton.Location = new System.Drawing.Point(6, 13);
this.SelectButton.Name = "SelectButton";
this.SelectButton.Size = new System.Drawing.Size(75, 23);
this.SelectButton.TabIndex = 0;
this.SelectButton.Text = "Select";
this.SelectButton.UseVisualStyleBackColor = true;
this.SelectButton.Click += new System.EventHandler(this.SelectButton_Click);
//
// ScanButton
//
this.ScanButton.Location = new System.Drawing.Point(87, 13);
this.ScanButton.Name = "ScanButton";
this.ScanButton.Size = new System.Drawing.Size(75, 23);
this.ScanButton.TabIndex = 1;
this.ScanButton.Text = "Scan";
this.ScanButton.UseVisualStyleBackColor = true;
this.ScanButton.Click += new System.EventHandler(this.ScanButton_Click);
//
// ValidationButton
//
this.ValidationButton.Location = new System.Drawing.Point(338, 13);
this.ValidationButton.Name = "ValidationButton";
this.ValidationButton.Size = new System.Drawing.Size(75, 23);
this.ValidationButton.TabIndex = 2;
this.ValidationButton.Text = "Validation";
this.ValidationButton.UseVisualStyleBackColor = true;
this.ValidationButton.Click += new System.EventHandler(this.ValidationButton_Click);
//
// ControlButton
//
this.ControlButton.Location = new System.Drawing.Point(344, 345);
this.ControlButton.Name = "ControlButton";
this.ControlButton.Size = new System.Drawing.Size(75, 23);
this.ControlButton.TabIndex = 6;
this.ControlButton.Text = "Save";
this.ControlButton.UseVisualStyleBackColor = true;
this.ControlButton.Click += new System.EventHandler(this.ControlButton_Click);
//
// Process
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(364, 397);
this.Controls.Add(this.ControlButton);
this.ClientSize = new System.Drawing.Size(455, 388);
this.Controls.Add(this.ConfigurationGroupBox);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (134)));
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.Name = "Process";
this.Padding = new System.Windows.Forms.Padding(12, 5, 12, 5);
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Create Process Mode";
this.Load += new System.EventHandler(this.ModeForm_Load);
this.ConfigurationGroupBox.ResumeLayout(false);
this.ConfigurationGroupBox.PerformLayout();
this.ProcessGroupBox.ResumeLayout(false);
this.ProcessGroupBox.PerformLayout();
this.contextMenuStrip.ResumeLayout(false);
this.containerControl1.ResumeLayout(false);
this.ProcessGroupBox.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button ScanButton;
private System.Windows.Forms.ContainerControl containerControl1;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip;
private System.Windows.Forms.ToolStripMenuItem DeleteToolStripMenuItem;
public System.Windows.Forms.GroupBox ConfigurationGroupBox;
private System.Windows.Forms.Label RemarkLabel;
private System.Windows.Forms.GroupBox ProcessGroupBox;
private System.Windows.Forms.ListBox RuleListBox;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.TextBox ProcessNameTextBox;
private System.Windows.Forms.Button AddButton;
private System.Windows.Forms.Button ScanButton;
private System.Windows.Forms.Button SelectButton;
public System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.Label FilenameLabel;
private System.Windows.Forms.TextBox FilenameTextBox;
private System.Windows.Forms.CheckBox UseCustomFilenameBox;
private RichTextBox RuleRichTextBox;
private Button ValidationButton;
}
}

View File

@@ -1,13 +1,14 @@
using System;
using Microsoft.WindowsAPICodePack.Dialogs;
using Netch.Controllers;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.WindowsAPICodePack.Dialogs;
using Netch.Controllers;
using Netch.Utils;
using Netch.Enums;
namespace Netch.Forms.Mode
{
@@ -16,176 +17,86 @@ namespace Netch.Forms.Mode
/// <summary>
/// 被编辑的模式
/// </summary>
private readonly Models.Mode _mode;
private readonly Models.Mode? _mode;
/// <summary>
/// 是否被编辑过
/// </summary>
public bool Edited { get; private set; }
/// <summary>
/// 编辑模式
/// 编辑模式
/// </summary>
/// <param name="mode">模式</param>
public Process(Models.Mode mode)
public Process(Models.Mode? mode = null)
{
if (mode.Type != 0)
{
throw new Exception("请传入进程模式");
}
if (mode != null && mode.Type is not ModeType.Process)
throw new ArgumentOutOfRangeException();
InitializeComponent();
Icon = Resources.icon;
CheckForIllegalCrossThreadCalls = false;
Text = "Edit Process Mode";
_mode = mode;
RuleListBox.Items.AddRange(mode.Rule.ToArray());
#region
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
FilenameTextBox.Enabled =
UseCustomFilenameBox.Enabled = false;
#endregion
FilenameTextBox.Text = mode.FileName;
RemarkTextBox.Text = mode.Remark;
}
public Process()
#region Model
public IEnumerable<string> Rules => RuleRichTextBox.Lines;
private void RuleAdd(string value)
{
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;
FilenameTextBox.Enabled = false;
RuleRichTextBox.AppendText($"{value}\n");
}
/// <summary>
/// 扫描目录
/// </summary>
/// <param name="DirName">路径</param>
public void ScanDirectory(string DirName)
private void RuleAddRange(IEnumerable<string> value)
{
try
foreach (string s in value)
{
var RDirInfo = new DirectoryInfo(DirName);
if (!RDirInfo.Exists)
{
return;
}
}
catch (Exception)
{
return;
}
var DirStack = new Stack<string>();
DirStack.Push(DirName);
while (DirStack.Count > 0)
{
var DirInfo = new DirectoryInfo(DirStack.Pop());
try
{
foreach (var DirChildInfo in DirInfo.GetDirectories())
{
DirStack.Push(DirChildInfo.FullName);
}
foreach (var FileChildInfo in DirInfo.GetFiles())
{
if (FileChildInfo.Name.EndsWith(".exe") && !RuleListBox.Items.Contains(FileChildInfo.Name))
{
RuleListBox.Items.Add(FileChildInfo.Name);
Edited = true;
}
}
}
catch (Exception)
{
// ignored
}
RuleAdd(s);
}
}
#endregion
public void ModeForm_Load(object sender, EventArgs e)
{
i18N.TranslateForm(this);
i18N.Translate(contextMenuStrip);
}
/// <summary>
/// listBox右键菜单
/// </summary>
private void RuleListBox_MouseUp(object sender, MouseEventArgs e)
{
RuleListBox.SelectedIndex = RuleListBox.IndexFromPoint(e.X, e.Y);
if (RuleListBox.SelectedIndex == -1)
return;
if (e.Button == MouseButtons.Right)
if (_mode != null)
{
contextMenuStrip.Show(RuleListBox, e.Location);
Text = "Edit Process Mode";
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
RemarkTextBox.Text = _mode.Remark;
FilenameTextBox.Text = _mode.RelativePath;
RuleAddRange(_mode.Content);
}
i18N.TranslateForm(this);
}
void deleteRule_Click(object sender, EventArgs e)
{
if (RuleListBox.SelectedIndex == -1) return;
RuleListBox.Items.RemoveAt(RuleListBox.SelectedIndex);
Edited = true;
}
private async void AddButton_Click(object sender, EventArgs e)
{
await Task.Run(() =>
{
if (string.IsNullOrWhiteSpace(ProcessNameTextBox.Text))
{
MessageBoxX.Show(i18N.Translate("Please enter an process name (xxx.exe)"));
return;
}
if (!NFController.CheckCppRegex(ProcessNameTextBox.Text))
{
MessageBoxX.Show("Rule does not conform to C++ regular expression syntax");
return;
}
var process = ProcessNameTextBox.Text;
if (!RuleListBox.Items.Contains(process))
{
RuleListBox.Items.Add(process);
}
Edited = true;
RuleListBox.SelectedIndex = RuleListBox.Items.IndexOf(process);
ProcessNameTextBox.Text = string.Empty;
});
}
private void ScanButton_Click(object sender, EventArgs e)
private void SelectButton_Click(object sender, EventArgs e)
{
var dialog = new CommonOpenFileDialog
{
IsFolderPicker = true,
Multiselect = false,
Multiselect = true,
Title = i18N.Translate("Select a folder"),
AddToMostRecentlyUsedList = false,
EnsurePathExists = true,
NavigateToShortcut = true
};
if (dialog.ShowDialog(Win32Native.GetForegroundWindow()) == CommonFileDialogResult.Ok)
if (dialog.ShowDialog(Handle) == CommonFileDialogResult.Ok)
{
ScanDirectory(dialog.FileName);
MessageBoxX.Show(i18N.Translate("Scan completed"));
foreach (string p in dialog.FileNames)
{
string path = p;
if (!path.EndsWith(@"\"))
path += @"\";
RuleAdd($"^{path.ToRegexString()}");
}
}
}
public void ControlButton_Click(object sender, EventArgs e)
{
if (RuleListBox.Items.Count == 0)
if (!RuleRichTextBox.Lines.Any())
{
MessageBoxX.Show(i18N.Translate("Unable to add empty rule"));
return;
@@ -206,61 +117,96 @@ namespace Netch.Forms.Mode
if (_mode != null)
{
_mode.Remark = RemarkTextBox.Text;
_mode.Rule.Clear();
_mode.Rule.AddRange(RuleListBox.Items.Cast<string>());
_mode.Content.Clear();
_mode.Content.AddRange(RuleRichTextBox.Lines);
ModeHelper.WriteFile(_mode);
Global.MainForm.InitMode();
Edited = false;
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
else
{
var fullName = ModeHelper.GetFullPath(FilenameTextBox.Text + ".txt");
var relativePath = FilenameTextBox.Text;
var fullName = ModeHelper.GetFullPath(relativePath);
if (File.Exists(fullName))
{
MessageBoxX.Show(i18N.Translate("File already exists.\n Please Change the filename"));
return;
}
var mode = new Models.Mode
var mode = new Models.Mode(fullName)
{
BypassChina = false,
FileName = FilenameTextBox.Text,
Type = 0,
Type = ModeType.Process,
Remark = RemarkTextBox.Text
};
mode.Rule.AddRange(RuleListBox.Items.Cast<string>());
ModeHelper.WriteFile(mode);
ModeHelper.Add(mode);
mode.Content.AddRange(RuleRichTextBox.Lines);
mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode added successfully"));
}
Close();
}
private async void RemarkTextBox_TextChanged(object sender, EventArgs e)
private void RemarkTextBox_TextChanged(object? sender, EventArgs? e)
{
await Task.Run(() =>
BeginInvoke(new Action(() =>
{
if (!UseCustomFilenameBox.Checked)
{
var invalidFileChars = Path.GetInvalidFileNameChars();
var fileName = new StringBuilder(RemarkTextBox.Text);
foreach (var c in invalidFileChars)
{
fileName.Replace(c, '_');
}
FilenameTextBox.Text = fileName.ToString();
}
});
FilenameTextBox.Text = FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text);
}));
}
private void UseCustomFilenameBox_CheckedChanged(object sender, EventArgs e)
private void ScanButton_Click(object sender, EventArgs e)
{
FilenameTextBox.Enabled = UseCustomFilenameBox.Checked;
var dialog = new CommonOpenFileDialog
{
IsFolderPicker = true,
Multiselect = false,
Title = i18N.Translate("Select a folder"),
AddToMostRecentlyUsedList = false,
EnsurePathExists = true,
NavigateToShortcut = true
};
if (dialog.ShowDialog(Handle) == CommonFileDialogResult.Ok)
{
var path = dialog.FileName;
var list = new List<string>();
const uint maxCount = 50;
try
{
ScanDirectory(path, list);
}
catch
{
MessageBoxX.Show(i18N.Translate($"The number of executable files in the \"{path}\" directory is greater than {maxCount}"),
LogLevel.WARNING);
return;
}
RuleAddRange(list);
}
}
private void ScanDirectory(string directory, List<string> list, uint maxCount = 30)
{
foreach (string dir in Directory.GetDirectories(directory))
ScanDirectory(dir, list, maxCount);
list.AddRange(
Directory.GetFiles(directory).Select(s => Path.GetFileName(s)).Where(s => s.EndsWith(".exe")).Select(s => s.ToRegexString()));
if (maxCount != 0 && list.Count > maxCount)
throw new Exception("The number of results is greater than maxCount");
}
private void ValidationButton_Click(object sender, EventArgs e)
{
if (!NFController.CheckRules(Rules, out var results))
MessageBoxX.Show(NFController.GenerateInvalidRulesMessage(results), LogLevel.WARNING);
else
MessageBoxX.Show("Fine");
}
}
}

File diff suppressed because it is too large Load Diff

197
Netch/Forms/Mode/Route.Designer.cs generated Normal file
View File

@@ -0,0 +1,197 @@
using System.ComponentModel;
using Netch.Properties;
namespace Netch.Forms.Mode
{
partial class Route
{
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.FilenameLabel = new System.Windows.Forms.Label();
this.FilenameTextBox = new System.Windows.Forms.TextBox();
this.ActionLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.containerControl1 = new System.Windows.Forms.ContainerControl();
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ControlButton = new System.Windows.Forms.Button();
this.ConfigurationGroupBox.SuspendLayout();
this.containerControl1.SuspendLayout();
this.contextMenuStrip.SuspendLayout();
this.SuspendLayout();
//
// ConfigurationGroupBox
//
this.ConfigurationGroupBox.Controls.Add(this.comboBox1);
this.ConfigurationGroupBox.Controls.Add(this.FilenameLabel);
this.ConfigurationGroupBox.Controls.Add(this.FilenameTextBox);
this.ConfigurationGroupBox.Controls.Add(this.ActionLabel);
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
this.ConfigurationGroupBox.Location = new System.Drawing.Point(8, 12);
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
this.ConfigurationGroupBox.Size = new System.Drawing.Size(340, 355);
this.ConfigurationGroupBox.TabIndex = 2;
this.ConfigurationGroupBox.TabStop = false;
this.ConfigurationGroupBox.Text = "Configuration";
//
// comboBox1
//
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(84, 49);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(138, 25);
this.comboBox1.TabIndex = 11;
//
// FilenameLabel
//
this.FilenameLabel.AutoSize = true;
this.FilenameLabel.Location = new System.Drawing.Point(12, 79);
this.FilenameLabel.Name = "FilenameLabel";
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
this.FilenameLabel.TabIndex = 6;
this.FilenameLabel.Text = "Filename";
//
// FilenameTextBox
//
this.FilenameTextBox.Location = new System.Drawing.Point(84, 76);
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.ReadOnly = true;
this.FilenameTextBox.Size = new System.Drawing.Size(250, 23);
this.FilenameTextBox.TabIndex = 5;
//
// ActionLabel
//
this.ActionLabel.AutoSize = true;
this.ActionLabel.Location = new System.Drawing.Point(12, 52);
this.ActionLabel.Name = "ActionLabel";
this.ActionLabel.Size = new System.Drawing.Size(44, 17);
this.ActionLabel.TabIndex = 0;
this.ActionLabel.Text = "Action";
//
// RemarkTextBox
//
this.RemarkTextBox.Location = new System.Drawing.Point(84, 22);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(250, 23);
this.RemarkTextBox.TabIndex = 1;
this.RemarkTextBox.TextChanged += new System.EventHandler(this.RemarkTextBox_TextChanged);
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
this.RemarkLabel.Location = new System.Drawing.Point(12, 25);
this.RemarkLabel.Name = "RemarkLabel";
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
this.RemarkLabel.TabIndex = 0;
this.RemarkLabel.Text = "Remark";
//
// containerControl1
//
this.containerControl1.Controls.Add(this.richTextBox1);
this.containerControl1.Location = new System.Drawing.Point(6, 103);
this.containerControl1.Name = "containerControl1";
this.containerControl1.Size = new System.Drawing.Size(328, 246);
this.containerControl1.TabIndex = 10;
this.containerControl1.Text = "containerControl1";
//
// richTextBox1
//
this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.richTextBox1.Location = new System.Drawing.Point(0, 0);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(328, 246);
this.richTextBox1.TabIndex = 0;
this.richTextBox1.Text = "";
//
// contextMenuStrip
//
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteToolStripMenuItem});
this.contextMenuStrip.Name = "contextMenuStrip";
this.contextMenuStrip.Size = new System.Drawing.Size(114, 26);
//
// DeleteToolStripMenuItem
//
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(113, 22);
this.DeleteToolStripMenuItem.Text = "Delete";
//
// ControlButton
//
this.ControlButton.Location = new System.Drawing.Point(273, 373);
this.ControlButton.Name = "ControlButton";
this.ControlButton.Size = new System.Drawing.Size(75, 23);
this.ControlButton.TabIndex = 3;
this.ControlButton.Text = "Save";
this.ControlButton.UseVisualStyleBackColor = true;
this.ControlButton.Click += new System.EventHandler(this.ControlButton_Click);
//
// Route
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(356, 419);
this.Controls.Add(this.ConfigurationGroupBox);
this.Controls.Add(this.ControlButton);
this.Name = "Route";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Create Route Table Rule";
this.Load += new System.EventHandler(this.Route_Load);
this.ConfigurationGroupBox.ResumeLayout(false);
this.ConfigurationGroupBox.PerformLayout();
this.containerControl1.ResumeLayout(false);
this.contextMenuStrip.ResumeLayout(false);
this.ResumeLayout(false);
}
public System.Windows.Forms.GroupBox ConfigurationGroupBox;
private System.Windows.Forms.ContainerControl containerControl1;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip;
public System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.ToolStripMenuItem DeleteToolStripMenuItem;
private System.Windows.Forms.Label FilenameLabel;
private System.Windows.Forms.TextBox FilenameTextBox;
private System.Windows.Forms.Label RemarkLabel;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.RichTextBox richTextBox1;
#endregion
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.Label ActionLabel;
}
}

102
Netch/Forms/Mode/Route.cs Normal file
View File

@@ -0,0 +1,102 @@
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.IO;
using System.Windows.Forms;
using Netch.Enums;
namespace Netch.Forms.Mode
{
public partial class Route : Form
{
private readonly TagItem<ModeType>[] _items =
{ new(ModeType.ProxyRuleIPs, "Proxy Rule IPs"), new(ModeType.BypassRuleIPs, "Bypass Rule IPs") };
private readonly Models.Mode? _mode;
public Route(Models.Mode? mode = null)
{
if (mode != null && mode.Type is not (ModeType.ProxyRuleIPs or ModeType.BypassRuleIPs))
throw new ArgumentOutOfRangeException();
_mode = mode;
InitializeComponent();
Icon = Resources.icon;
comboBox1.DataSource = _items;
comboBox1.ValueMember = nameof(TagItem<int>.Value);
comboBox1.DisplayMember = nameof(TagItem<int>.Text);
}
private void Route_Load(object sender, EventArgs e)
{
if (_mode != null)
{
Text = "Edit Route Table Rule";
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
RemarkTextBox.Text = _mode.Remark;
comboBox1.SelectedValue = _mode.Type; // ComboBox SelectedValue worked after ctor
FilenameTextBox.Text = _mode.RelativePath;
richTextBox1.Lines = _mode.Content.ToArray();
}
i18N.TranslateForm(this);
}
private void ControlButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(RemarkTextBox.Text))
{
MessageBoxX.Show(i18N.Translate("Please enter a mode remark"));
return;
}
if (string.IsNullOrWhiteSpace(FilenameTextBox.Text))
{
MessageBoxX.Show(i18N.Translate("Please enter a mode filename"));
return;
}
if (_mode != null)
{
_mode.Remark = RemarkTextBox.Text;
_mode.Content.Clear();
_mode.Content.AddRange(richTextBox1.Lines);
_mode.Type = (ModeType)comboBox1.SelectedValue;
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
else
{
var relativePath = FilenameTextBox.Text;
var fullName = ModeHelper.GetFullPath(relativePath);
if (File.Exists(fullName))
{
MessageBoxX.Show(i18N.Translate("File already exists.\n Please Change the filename"));
return;
}
var mode = new Models.Mode(fullName)
{
Type = (ModeType)comboBox1.SelectedValue,
Remark = RemarkTextBox.Text
};
mode.Content.AddRange(richTextBox1.Lines);
mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode added successfully"));
}
Close();
}
private void RemarkTextBox_TextChanged(object? sender, EventArgs? e)
{
BeginInvoke(new Action(() => { FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text); }));
}
}
}

View File

@@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -1,39 +1,56 @@
using System.ComponentModel;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
#nullable disable
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace Netch.Forms
{
[DesignerCategory(@"Code")]
public abstract class ServerForm : Form
{
protected abstract string TypeName { get; }
protected Server Server { get; set; }
private int _controlLines = 2;
private const int ControlLineHeight = 28;
private const int InputBoxWidth = 294;
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new();
private readonly Dictionary<Control, Action<object>> _saveActions = new();
private int _controlLines = 2;
private Label AddressLabel;
protected TextBox AddressTextBox;
private readonly IContainer components = null;
private GroupBox ConfigurationGroupBox;
private Label PortLabel;
private TextBox PortTextBox;
private Label RemarkLabel;
protected TextBox RemarkTextBox;
protected ServerForm()
{
InitializeComponent();
_checkActions.Add(RemarkTextBox, s => true);
_saveActions.Add(RemarkTextBox, s => Server.Remark = (string) s);
_saveActions.Add(RemarkTextBox, s => Server.Remark = (string)s);
_checkActions.Add(AddressTextBox, s => s != string.Empty);
_saveActions.Add(AddressTextBox, s => Server.Hostname = (string) s);
_saveActions.Add(AddressTextBox, s => Server.Hostname = (string)s);
_checkActions.Add(PortTextBox, s => ushort.TryParse(s, out var port) && port != 0);
_saveActions.Add(PortTextBox, s => Server.Port = ushort.Parse((string) s));
_saveActions.Add(PortTextBox, s => Server.Port = ushort.Parse((string)s));
}
protected abstract string TypeName { get; }
protected Server Server { get; set; }
public new void ShowDialog()
{
AfterFactor();
@@ -63,7 +80,12 @@ namespace Netch.Forms
PerformLayout();
}
protected void CreateTextBox(string name, string remark, Func<string, bool> check, Action<string> save, string value, int width = InputBoxWidth)
protected void CreateTextBox(string name,
string remark,
Func<string, bool> check,
Action<string> save,
string value,
int width = InputBoxWidth)
{
_controlLines++;
@@ -75,22 +97,21 @@ namespace Netch.Forms
TextAlign = HorizontalAlignment.Center,
Text = value
};
_checkActions.Add(textBox, check);
_saveActions.Add(textBox, o => save.Invoke((string) o));
ConfigurationGroupBox.Controls.AddRange(
new Control[]
_saveActions.Add(textBox, o => save.Invoke((string)o));
ConfigurationGroupBox.Controls.AddRange(new Control[]
{
textBox,
new Label
{
textBox,
new Label
{
AutoSize = true,
Location = new Point(10, ControlLineHeight * _controlLines),
Name = $"{name}Label",
Size = new Size(56, 17),
Text = remark
}
AutoSize = true,
Location = new Point(10, ControlLineHeight * _controlLines),
Name = $"{name}Label",
Size = new Size(56, 17),
Text = remark
}
);
});
}
protected void CreateComboBox(string name, string remark, List<string> values, Action<string> save, string value, int width = InputBoxWidth)
@@ -106,24 +127,23 @@ namespace Netch.Forms
DropDownStyle = ComboBoxStyle.DropDownList,
FormattingEnabled = true
};
comboBox.Items.AddRange(values.ToArray());
comboBox.SelectedIndex = values.IndexOf(value);
comboBox.DrawItem += Utils.Utils.DrawCenterComboBox;
_saveActions.Add(comboBox, o => save.Invoke((string) o));
ConfigurationGroupBox.Controls.AddRange(
new Control[]
_saveActions.Add(comboBox, o => save.Invoke((string)o));
ConfigurationGroupBox.Controls.AddRange(new Control[]
{
comboBox,
new Label
{
comboBox,
new Label
{
AutoSize = true,
Location = new Point(10, ControlLineHeight * _controlLines),
Name = $"{name}Label",
Size = new Size(56, 17),
Text = remark
}
AutoSize = true,
Location = new Point(10, ControlLineHeight * _controlLines),
Name = $"{name}Label",
Size = new Size(56, 17),
Text = remark
}
);
});
}
protected void CreateCheckBox(string name, string remark, Action<bool> save, bool value)
@@ -138,19 +158,14 @@ namespace Netch.Forms
Checked = value,
Text = remark
};
_saveActions.Add(checkBox, o => save.Invoke((bool) o));
ConfigurationGroupBox.Controls.AddRange(
new Control[]
{
checkBox
}
);
_saveActions.Add(checkBox, o => save.Invoke((bool)o));
ConfigurationGroupBox.Controls.AddRange(new Control[]
{
checkBox
});
}
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new Dictionary<Control, Func<string, bool>>();
private readonly Dictionary<Control, Action<object>> _saveActions = new Dictionary<Control, Action<object>>();
private void AddSaveButton()
{
_controlLines++;
@@ -162,6 +177,7 @@ namespace Netch.Forms
Text = "Save",
UseVisualStyleBackColor = true
};
control.Click += ControlButton_Click;
ConfigurationGroupBox.Controls.Add(control);
}
@@ -178,12 +194,9 @@ namespace Netch.Forms
}
if (!flag)
{
return;
}
foreach (var pair in _saveActions)
{
switch (pair.Key)
{
case CheckBox c:
@@ -193,7 +206,6 @@ namespace Netch.Forms
pair.Value.Invoke(pair.Key.Text);
break;
}
}
if (Global.Settings.Server.IndexOf(Server) == -1)
Global.Settings.Server.Add(Server);
@@ -203,14 +215,10 @@ namespace Netch.Forms
Close();
}
private IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing)
{
components?.Dispose();
}
base.Dispose(disposing);
}
@@ -304,7 +312,7 @@ namespace Netch.Forms
AutoSizeMode = AutoSizeMode.GrowAndShrink;
ClientSize = new Size(444, 137);
Controls.Add(ConfigurationGroupBox);
Font = new Font("微软雅黑", 9F, FontStyle.Regular, GraphicsUnit.Point, (byte) 134);
Font = new Font("微软雅黑", 9F, FontStyle.Regular, GraphicsUnit.Point, 134);
FormBorderStyle = FormBorderStyle.FixedSingle;
Icon = Icon.FromHandle(Resources.Netch.GetHicon());
Margin = new Padding(3, 4, 3, 4);
@@ -313,13 +321,5 @@ namespace Netch.Forms
Padding = new Padding(11, 5, 11, 4);
StartPosition = FormStartPosition.CenterScreen;
}
private GroupBox ConfigurationGroupBox;
private Label RemarkLabel;
protected TextBox RemarkTextBox;
private Label PortLabel;
protected TextBox AddressTextBox;
private TextBox PortTextBox;
private Label AddressLabel;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,13 @@
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using Netch.Utils;
namespace Netch.Forms
{
@@ -15,107 +16,109 @@ namespace Netch.Forms
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new();
private readonly Dictionary<Control, Action<Control>> _saveActions = new();
public SettingForm()
{
InitializeComponent();
Icon = Resources.icon;
i18N.TranslateForm(this);
InitValue();
}
private void SettingForm_Load(object sender, EventArgs e)
{
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
Task.Run(() => BeginInvoke(new Action(() => UseFakeDNSCheckBox.Visible = Global.Flags.SupportFakeDns)));
}
private void InitValue()
{
#region General
BindTextBox<ushort>(Socks5PortTextBox,
p => p.ToString() != HTTPPortTextBox.Text && p.ToString() != RedirectorTextBox.Text,
p => p.ToString() != HTTPPortTextBox.Text,
p => Global.Settings.Socks5LocalPort = p,
Global.Settings.Socks5LocalPort);
BindTextBox<ushort>(HTTPPortTextBox,
p => p.ToString() != Socks5PortTextBox.Text && p.ToString() != RedirectorTextBox.Text,
p => p.ToString() != Socks5PortTextBox.Text,
p => Global.Settings.HTTPLocalPort = p,
Global.Settings.HTTPLocalPort);
BindTextBox<ushort>(RedirectorTextBox,
p => p.ToString() != Socks5PortTextBox.Text && p.ToString() != HTTPPortTextBox.Text,
p => Global.Settings.RedirectorTCPPort = p,
Global.Settings.RedirectorTCPPort);
BindCheckBox(AllowDevicesCheckBox,
c => Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1",
Global.Settings.LocalAddress switch
{
"127.0.0.1" => false,
"0.0.0.0" => true,
_ => false
});
Global.Settings.LocalAddress switch { "127.0.0.1" => false, "0.0.0.0" => true, _ => false });
BindCheckBox(BootShadowsocksFromDLLCheckBox,
c => Global.Settings.BootShadowsocksFromDLL = c,
Global.Settings.BootShadowsocksFromDLL);
BindCheckBox(ResolveServerHostnameCheckBox,
c => Global.Settings.ResolveServerHostname = c,
Global.Settings.ResolveServerHostname);
BindCheckBox(ResolveServerHostnameCheckBox, c => Global.Settings.ResolveServerHostname = c, Global.Settings.ResolveServerHostname);
BindRadioBox(ICMPingRadioBtn,
_ => { },
!Global.Settings.ServerTCPing);
BindRadioBox(ICMPingRadioBtn, _ => { }, !Global.Settings.ServerTCPing);
BindRadioBox(TCPingRadioBtn,
c => Global.Settings.ServerTCPing = c,
Global.Settings.ServerTCPing);
BindRadioBox(TCPingRadioBtn, c => Global.Settings.ServerTCPing = c, Global.Settings.ServerTCPing);
BindTextBox<int>(ProfileCountTextBox,
i => i > -1,
i => Global.Settings.ProfileCount = i,
Global.Settings.ProfileCount);
BindTextBox<int>(ProfileCountTextBox, i => i > -1, i => Global.Settings.ProfileCount = i, Global.Settings.ProfileCount);
BindTextBox<int>(DetectionTickTextBox,
i => i >= 0,
i => ServerHelper.DelayTestHelper.Range.InRange(i),
i => Global.Settings.DetectionTick = i,
Global.Settings.DetectionTick);
BindTextBox<int>(StartedPingIntervalTextBox,
_ => true,
i => Global.Settings.StartedPingInterval = i,
Global.Settings.StartedPingInterval);
InitSTUN();
object[]? stuns;
try
{
stuns = File.ReadLines("bin\\stun.txt").Cast<object>().ToArray();
}
catch (Exception e)
{
Global.Logger.Warning($"Load stun.txt failed: {e.Message}");
stuns = null;
}
BindTextBox<string>(AclAddrTextBox,
s => true,
s => Global.Settings.ACL = s,
Global.Settings.ACL);
AclAddrTextBox.Text = Global.Settings.ACL;
BindComboBox(STUN_ServerComboBox,
s =>
{
var split = s.SplitRemoveEmptyEntriesAndTrimEntries(':');
if (!split.Any())
return false;
LanguageComboBox.Items.AddRange(i18N.GetTranslateList().ToArray());
LanguageComboBox.SelectedItem = Global.Settings.Language;
var port = split.ElementAtOrDefault(1);
if (port != null)
if (!ushort.TryParse(split[1], out _))
return false;
return true;
},
o =>
{
var split = o.ToString().SplitRemoveEmptyEntriesAndTrimEntries(':');
Global.Settings.STUN_Server = split[0];
var port = split.ElementAtOrDefault(1);
Global.Settings.STUN_Server_Port = port != null ? ushort.Parse(port) : 3478;
},
Global.Settings.STUN_Server + ":" + Global.Settings.STUN_Server_Port,
stuns);
BindListComboBox(LanguageComboBox, o => Global.Settings.Language = o.ToString(), i18N.GetTranslateList(), Global.Settings.Language);
#endregion
#region Process Mode
BindCheckBox(ModifySystemDNSCheckBox,
b => Global.Settings.ModifySystemDNS = b,
Global.Settings.ModifySystemDNS);
BindCheckBox(DNSHijackCheckBox, b => Global.Settings.Redirector.DNSHijack = b, Global.Settings.Redirector.DNSHijack);
BindTextBox(ModifiedDNSTextBox,
s => DNS.TrySplit(s, out _, 2),
s => Global.Settings.ModifiedDNS = s,
Global.Settings.ModifiedDNS);
BindTextBox(DNSHijackHostTextBox, s => true, s => Global.Settings.Redirector.DNSHijackHost = s, Global.Settings.Redirector.DNSHijackHost);
BindCheckBox(RedirectorSSCheckBox,
s => Global.Settings.RedirectorSS = s,
Global.Settings.RedirectorSS);
BindCheckBox(ICMPHijackCheckBox, b => Global.Settings.Redirector.ICMPHijack = b, Global.Settings.Redirector.ICMPHijack);
BindCheckBox(NoProxyForUdpCheckBox,
s => Global.Settings.ProcessNoProxyForUdp = s,
Global.Settings.ProcessNoProxyForUdp);
BindTextBox(ICMPHijackHostTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.Redirector.ICMPHost = s,
Global.Settings.Redirector.ICMPHost);
BindCheckBox(NoProxyForTcpCheckBox,
s => Global.Settings.ProcessNoProxyForTcp = s,
Global.Settings.ProcessNoProxyForTcp);
BindCheckBox(RedirectorSSCheckBox, s => Global.Settings.Redirector.RedirectorSS = s, Global.Settings.Redirector.RedirectorSS);
BindCheckBox(ChildProcessHandleCheckBox,
s => Global.Settings.Redirector.ChildProcessHandle = s,
Global.Settings.Redirector.ChildProcessHandle);
BindListComboBox(ProcessProxyProtocolComboBox,
s => Global.Settings.Redirector.ProxyProtocol = (PortType)Enum.Parse(typeof(PortType), s.ToString(), false),
Enum.GetNames(typeof(PortType)),
Global.Settings.Redirector.ProxyProtocol.ToString());
#endregion
@@ -125,83 +128,61 @@ namespace Netch.Forms
s => IPAddress.TryParse(s, out _),
s => Global.Settings.TUNTAP.Address = s,
Global.Settings.TUNTAP.Address);
BindTextBox(TUNTAPNetmaskTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.TUNTAP.Netmask = s,
Global.Settings.TUNTAP.Netmask);
BindTextBox(TUNTAPGatewayTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.TUNTAP.Gateway = s,
Global.Settings.TUNTAP.Gateway);
BindCheckBox(UseCustomDNSCheckBox,
b => { Global.Settings.TUNTAP.UseCustomDNS = b; },
Global.Settings.TUNTAP.UseCustomDNS);
BindCheckBox(UseCustomDNSCheckBox, b => { Global.Settings.TUNTAP.UseCustomDNS = b; }, Global.Settings.TUNTAP.UseCustomDNS);
BindTextBox(TUNTAPDNSTextBox,
s => !UseCustomDNSCheckBox.Checked || DNS.TrySplit(s, out _, 2),
_ => true,
s =>
{
if (UseCustomDNSCheckBox.Checked)
Global.Settings.TUNTAP.DNS = DNS.Split(s).ToList();
Global.Settings.TUNTAP.HijackDNS = s;
},
DNS.Join(Global.Settings.TUNTAP.DNS));
Global.Settings.TUNTAP.HijackDNS);
BindCheckBox(ProxyDNSCheckBox,
b => Global.Settings.TUNTAP.ProxyDNS = b,
Global.Settings.TUNTAP.ProxyDNS);
BindCheckBox(UseFakeDNSCheckBox,
b => Global.Settings.TUNTAP.UseFakeDNS = b,
Global.Settings.TUNTAP.UseFakeDNS);
try
{
var icsHelperEnabled = ICSHelper.Enabled;
if (icsHelperEnabled != null)
{
ICSCheckBox.Enabled = true;
ICSCheckBox.Checked = (bool) icsHelperEnabled;
}
}
catch
{
// ignored
}
BindCheckBox(ProxyDNSCheckBox, b => Global.Settings.TUNTAP.ProxyDNS = b, Global.Settings.TUNTAP.ProxyDNS);
#endregion
#region V2Ray
BindCheckBox(TLSAllowInsecureCheckBox,
b => Global.Settings.V2RayConfig.AllowInsecure = b,
Global.Settings.V2RayConfig.AllowInsecure);
BindCheckBox(UseMuxCheckBox,
b => Global.Settings.V2RayConfig.UseMux = b,
Global.Settings.V2RayConfig.UseMux);
BindCheckBox(XrayConeCheckBox, b => Global.Settings.V2RayConfig.XrayCone = b, Global.Settings.V2RayConfig.XrayCone);
BindTextBox<int>(mtuTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.mtu = i,
Global.Settings.V2RayConfig.KcpConfig.mtu);
BindTextBox<int>(ttiTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.tti = i,
Global.Settings.V2RayConfig.KcpConfig.tti);
BindCheckBox(TLSAllowInsecureCheckBox, b => Global.Settings.V2RayConfig.AllowInsecure = b, Global.Settings.V2RayConfig.AllowInsecure);
BindCheckBox(UseMuxCheckBox, b => Global.Settings.V2RayConfig.UseMux = b, Global.Settings.V2RayConfig.UseMux);
BindTextBox<int>(mtuTextBox, i => true, i => Global.Settings.V2RayConfig.KcpConfig.mtu = i, Global.Settings.V2RayConfig.KcpConfig.mtu);
BindTextBox<int>(ttiTextBox, i => true, i => Global.Settings.V2RayConfig.KcpConfig.tti = i, Global.Settings.V2RayConfig.KcpConfig.tti);
BindTextBox<int>(uplinkCapacityTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity = i,
Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity);
BindTextBox<int>(downlinkCapacityTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity = i,
Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity);
BindTextBox<int>(readBufferSizeTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.readBufferSize = i,
Global.Settings.V2RayConfig.KcpConfig.readBufferSize);
BindTextBox<int>(writeBufferSizeTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.writeBufferSize = i,
Global.Settings.V2RayConfig.KcpConfig.writeBufferSize);
BindCheckBox(congestionCheckBox,
b => Global.Settings.V2RayConfig.KcpConfig.congestion = b,
Global.Settings.V2RayConfig.KcpConfig.congestion);
@@ -210,83 +191,49 @@ namespace Netch.Forms
#region Others
BindCheckBox(ExitWhenClosedCheckBox,
b => Global.Settings.ExitWhenClosed = b,
Global.Settings.ExitWhenClosed);
BindCheckBox(ExitWhenClosedCheckBox, b => Global.Settings.ExitWhenClosed = b, Global.Settings.ExitWhenClosed);
BindCheckBox(StopWhenExitedCheckBox,
b => Global.Settings.StopWhenExited = b,
Global.Settings.StopWhenExited);
BindCheckBox(StopWhenExitedCheckBox, b => Global.Settings.StopWhenExited = b, Global.Settings.StopWhenExited);
BindCheckBox(StartWhenOpenedCheckBox,
b => Global.Settings.StartWhenOpened = b,
Global.Settings.StartWhenOpened);
BindCheckBox(StartWhenOpenedCheckBox, b => Global.Settings.StartWhenOpened = b, Global.Settings.StartWhenOpened);
BindCheckBox(MinimizeWhenStartedCheckBox,
b => Global.Settings.MinimizeWhenStarted = b,
Global.Settings.MinimizeWhenStarted);
BindCheckBox(MinimizeWhenStartedCheckBox, b => Global.Settings.MinimizeWhenStarted = b, Global.Settings.MinimizeWhenStarted);
BindCheckBox(RunAtStartupCheckBox,
b => Global.Settings.RunAtStartup = b,
Global.Settings.RunAtStartup);
BindCheckBox(RunAtStartupCheckBox, b => Global.Settings.RunAtStartup = b, Global.Settings.RunAtStartup);
BindCheckBox(CheckUpdateWhenOpenedCheckBox,
b => Global.Settings.CheckUpdateWhenOpened = b,
Global.Settings.CheckUpdateWhenOpened);
BindCheckBox(CheckUpdateWhenOpenedCheckBox, b => Global.Settings.CheckUpdateWhenOpened = b, Global.Settings.CheckUpdateWhenOpened);
BindCheckBox(CheckBetaUpdateCheckBox,
b => Global.Settings.CheckBetaUpdate = b,
Global.Settings.CheckBetaUpdate);
BindCheckBox(CheckBetaUpdateCheckBox, b => Global.Settings.CheckBetaUpdate = b, Global.Settings.CheckBetaUpdate);
BindCheckBox(UpdateServersWhenOpenedCheckBox,
b => Global.Settings.UpdateServersWhenOpened = b,
Global.Settings.UpdateServersWhenOpened);
BindCheckBox(UpdateServersWhenOpenedCheckBox, b => Global.Settings.UpdateServersWhenOpened = b, Global.Settings.UpdateServersWhenOpened);
#endregion
#region AioDNS
BindTextBox(AioDNSRulePathTextBox,
s => true,
s => Global.Settings.AioDNS.RulePath = s,
Global.Settings.AioDNS.RulePath);
BindTextBox(ChinaDNSTextBox, _ => true, s => Global.Settings.AioDNS.ChinaDNS = s, Global.Settings.AioDNS.ChinaDNS);
BindTextBox(ChinaDNSTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.AioDNS.ChinaDNS = s,
Global.Settings.AioDNS.ChinaDNS);
BindTextBox(OtherDNSTextBox, _ => true, s => Global.Settings.AioDNS.OtherDNS = s, Global.Settings.AioDNS.OtherDNS);
BindTextBox(OtherDNSTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.AioDNS.OtherDNS = s,
Global.Settings.AioDNS.OtherDNS);
BindTextBox(AioDNSListenPortTextBox,
s => ushort.TryParse(s, out _),
s => Global.Settings.AioDNS.ListenPort = ushort.Parse(s),
Global.Settings.AioDNS.ListenPort);
#endregion
}
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object sender, EventArgs e)
private void SettingForm_Load(object sender, EventArgs e)
{
if (UseCustomDNSCheckBox.Checked)
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.DNS.Any()
? DNS.Join(Global.Settings.TUNTAP.DNS)
: "1.1.1.1";
else
TUNTAPDNSTextBox.Text = "AioDNS";
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
}
private void InitSTUN()
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object? sender, EventArgs? e)
{
try
{
var stuns = File.ReadLines("bin\\stun.txt");
STUN_ServerComboBox.Items.AddRange(stuns.ToArray());
}
catch
{
// ignored
}
STUN_ServerComboBox.Text = $"{Global.Settings.STUN_Server}:{Global.Settings.STUN_Server_Port}";
if (UseCustomDNSCheckBox.Checked)
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.HijackDNS;
else
TUNTAPDNSTextBox.Text = "AioDNS";
}
private void GlobalBypassIPsButton_Click(object sender, EventArgs e)
@@ -302,55 +249,20 @@ namespace Netch.Forms
#region Check
var flag = true;
foreach (var pair in _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)))
{
Utils.Utils.ChangeControlForeColor(pair.Key, Color.Red);
flag = false;
}
var checkNotPassControl = _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)).Select(pair => pair.Key).ToList();
foreach (Control control in checkNotPassControl)
Utils.Utils.ChangeControlForeColor(control, Color.Red);
if (!flag)
if (checkNotPassControl.Any())
return;
#endregion
#region CheckSTUN
var errFlag = false;
var stunServer = string.Empty;
ushort stunServerPort = 3478;
var stun = STUN_ServerComboBox.Text.Split(':');
if (stun.Any())
{
stunServer = stun[0];
if (stun.Length > 1)
if (!ushort.TryParse(stun[1], out stunServerPort))
errFlag = true;
}
else
{
errFlag = true;
}
if (errFlag)
{
Utils.Utils.ChangeControlForeColor(STUN_ServerComboBox, Color.Red);
return;
}
#endregion
#region Save
foreach (var pair in _saveActions)
pair.Value.Invoke(pair.Key);
Global.Settings.STUN_Server = stunServer;
Global.Settings.STUN_Server_Port = stunServerPort;
Global.Settings.Language = LanguageComboBox.Text;
#endregion
Utils.Utils.RegisterNetchStartupItem();
@@ -360,34 +272,7 @@ namespace Netch.Forms
Close();
}
private async void ICSCheckBox_CheckedChanged(object sender, EventArgs e)
{
try
{
ICSCheckBox.Enabled = false;
await Task.Run(() =>
{
if (ICSCheckBox.Checked)
{
if (!(ICSHelper.Enabled ?? true))
ICSCheckBox.Checked = ICSHelper.Enable();
}
else
{
ICSHelper.Disable();
}
});
}
catch (Exception exception)
{
ICSCheckBox.Checked = false;
Logging.Error(exception.ToString());
}
finally
{
ICSCheckBox.Enabled = true;
}
}
#region BindUtils
private void BindTextBox(TextBox control, Func<string, bool> check, Action<string> save, object value)
{
@@ -397,39 +282,60 @@ namespace Netch.Forms
private void BindTextBox<T>(TextBox control, Func<T, bool> check, Action<T> save, object value)
{
control.Text = value.ToString();
_checkActions.Add(control, s =>
{
try
_checkActions.Add(control,
s =>
{
return check.Invoke((T) Convert.ChangeType(s, typeof(T)));
}
catch
{
return false;
}
});
_saveActions.Add(control, c => save.Invoke((T) Convert.ChangeType(((TextBox) c).Text, typeof(T))));
try
{
return check.Invoke((T)Convert.ChangeType(s, typeof(T)));
}
catch
{
return false;
}
});
_saveActions.Add(control, c => save.Invoke((T)Convert.ChangeType(((TextBox)c).Text, typeof(T))));
}
private void BindCheckBox(CheckBox control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((CheckBox) c).Checked));
_saveActions.Add(control, c => save.Invoke(((CheckBox)c).Checked));
}
private void BindRadioBox(RadioButton control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((RadioButton) c).Checked));
_saveActions.Add(control, c => save.Invoke(((RadioButton)c).Checked));
}
private void NoProxyForUdpCheckBox_CheckedChanged(object sender, EventArgs e)
private void BindListComboBox<T>(ComboBox comboBox, Action<T> save, IEnumerable<T> values, T value) where T : notnull
{
if (NoProxyForUdpCheckBox.Checked) NoProxyForTcpCheckBox.Checked = false;
if (comboBox.DropDownStyle != ComboBoxStyle.DropDownList)
throw new ArgumentOutOfRangeException();
var tagItems = values.Select(o => new TagItem<T>(o, o.ToString()!)).ToArray();
comboBox.Items.AddRange(tagItems.Cast<object>().ToArray());
comboBox.ValueMember = nameof(TagItem<T>.Value);
comboBox.DisplayMember = nameof(TagItem<T>.Text);
_saveActions.Add(comboBox, c => save.Invoke(((TagItem<T>)((ComboBox)c).SelectedItem).Value));
Load += (_, _) => { comboBox.SelectedItem = tagItems.SingleOrDefault(t => t.Value.Equals(value)); };
}
private void NoProxyForTcpCheckBox_CheckedChanged(object sender, EventArgs e)
private void BindComboBox(ComboBox control, Func<string, bool> check, Action<string> save, string value, object[]? values = null)
{
if (NoProxyForTcpCheckBox.Checked) NoProxyForUdpCheckBox.Checked = false;
if (values != null)
control.Items.AddRange(values);
_saveActions.Add(control, c => save.Invoke(((ComboBox)c).Text));
_checkActions.Add(control, check.Invoke);
Load += (_, _) => { control.Text = value; };
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -235,7 +235,6 @@
this.Controls.Add(this.MainTableLayoutPanel);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.Name = "SubscribeForm";

View File

@@ -1,8 +1,9 @@
using System;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Linq;
using System.Windows.Forms;
using Netch.Models;
using Netch.Utils;
namespace Netch.Forms
{
@@ -11,6 +12,7 @@ namespace Netch.Forms
public SubscribeForm()
{
InitializeComponent();
Icon = Resources.icon;
i18N.TranslateForm(this);
i18N.TranslateForm(pContextMenuStrip);
@@ -83,7 +85,8 @@ namespace Netch.Forms
return;
}
if (!LinkTextBox.Text.StartsWith("HTTP://", StringComparison.OrdinalIgnoreCase) && !LinkTextBox.Text.StartsWith("HTTPS://", StringComparison.OrdinalIgnoreCase))
if (!LinkTextBox.Text.StartsWith("HTTP://", StringComparison.OrdinalIgnoreCase) &&
!LinkTextBox.Text.StartsWith("HTTPS://", StringComparison.OrdinalIgnoreCase))
{
MessageBoxX.Show(i18N.Translate("Link must start with http:// or https://"));
return;
@@ -115,8 +118,6 @@ namespace Netch.Forms
subscribeLink.UserAgent = UserAgentTextBox.Text;
}
MessageBoxX.Show(i18N.Translate("Saved"));
InitSubscribeLink();
}
@@ -126,7 +127,8 @@ namespace Netch.Forms
private void DeleteToolStripMenuItem_Click(object sender, EventArgs e)
{
if (MessageBoxX.Show(i18N.Translate("Delete or not ? Will clean up the corresponding group of items in the server list"), confirm: true) != DialogResult.OK)
if (MessageBoxX.Show(i18N.Translate("Delete or not ? Will clean up the corresponding group of items in the server list"),
confirm: true) != DialogResult.OK)
return;
var subscribeLink = Global.Settings.SubscribeLink[SelectedIndex];
@@ -190,6 +192,7 @@ namespace Netch.Forms
LinkTextBox.Text = string.Empty;
UserAgentTextBox.Text = WebUtil.DefaultUserAgent;
}
private void SetEditingGroup(int index)
{
if (index == -1)

File diff suppressed because it is too large Load Diff

View File

@@ -1,96 +1,58 @@
using Netch.Controllers;
using Netch.Forms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Loggers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Windows.Forms;
using WindowsJobAPI;
namespace Netch
{
public static class Global
{
/// <summary>
/// 换行
/// </summary>
public const string EOF = "\r\n";
public static readonly string NetchDir = Application.StartupPath;
/// <summary>
/// 主窗体的静态实例
/// </summary>
public static MainForm MainForm;
public static class Flags
{
public static bool SupportFakeDns => _supportFakeDns ??= new TUNTAPController().TestFakeDNS();
public static readonly bool IsWindows10Upper = Environment.OSVersion.Version.Major >= 10;
private static bool? _supportFakeDns;
}
/// <summary>
/// 出口适配器
/// </summary>
public static class Outbound
{
/// <summary>
/// 索引
/// </summary>
public static int Index = -1;
/// <summary>
/// 地址
/// </summary>
public static IPAddress Address => Adapter.GetIPProperties().UnicastAddresses.First(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork).Address;
/// <summary>
/// 网关
/// </summary>
public static IPAddress Gateway;
public static NetworkInterface Adapter;
}
/// <summary>
/// TUN/TAP 适配器
/// </summary>
public static class TUNTAP
{
/// <summary>
/// 适配器
/// </summary>
public static NetworkInterface Adapter;
/// <summary>
/// 索引
/// </summary>
public static int Index = -1;
/// <summary>
/// 组件 ID
/// </summary>
public static string ComponentID = string.Empty;
}
private static readonly Lazy<MainForm> LazyMainForm = new(() => new MainForm());
/// <summary>
/// 用于读取和写入的配置
/// </summary>
public static Setting Settings = new Setting();
public static Setting Settings = new();
/// <summary>
/// 用于存储模式
/// </summary>
public static readonly List<Mode> Modes = new List<Mode>();
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>
/// Windows Job API
/// 主窗体的静态实例
/// </summary>
public static readonly JobObject Job = new JobObject();
public static MainForm MainForm => LazyMainForm.Value;
public static JsonSerializerOptions NewDefaultJsonSerializerOptions => new()
{
WriteIndented = true,
IgnoreNullValues = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
}
}

View File

@@ -1,4 +1,4 @@
namespace Netch.Controllers
namespace Netch.Interfaces
{
public interface IController
{
@@ -10,6 +10,6 @@
/// <summary>
/// 停止
/// </summary>
public abstract void Stop();
public void Stop();
}
}

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();
}
}

View File

@@ -1,6 +1,6 @@
using Netch.Models;
namespace Netch.Controllers
namespace Netch.Interfaces
{
public interface IModeController : IController
{
@@ -9,6 +9,6 @@ namespace Netch.Controllers
/// </summary>
/// <param name="mode">模式</param>
/// <returns>是否成功</returns>
public abstract bool Start(in Mode mode);
public abstract void Start(in Mode mode);
}
}

View File

@@ -1,12 +1,12 @@
using Netch.Models;
namespace Netch.Controllers
namespace Netch.Interfaces
{
public interface IServerController : IController
{
public ushort? Socks5LocalPort { get; set; }
public string LocalAddress { get; set; }
public string? LocalAddress { get; set; }
/// <summary>
/// 启动
@@ -14,7 +14,7 @@ namespace Netch.Controllers
/// <param name="s">服务器</param>
/// <param name="mode">模式</param>
/// <returns>是否启动成功</returns>
public abstract bool Start(in Server s, in Mode mode);
public abstract void Start(in Server s, in Mode mode);
}
public static class ServerControllerExtension

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
using Netch.Controllers;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using Netch.Models;
namespace Netch.Models
namespace Netch.Interfaces
{
public interface IServerUtil
{
@@ -28,7 +28,7 @@ namespace Netch.Models
/// </summary>
string[] UriScheme { get; }
Server ParseJObject(in JObject j);
public Type ServerType { get; }
public void Edit(Server s);
@@ -36,9 +36,9 @@ namespace Netch.Models
string GetShareLink(Server s);
public abstract IServerController GetController();
public IServerController GetController();
public abstract IEnumerable<Server> ParseUri(string text);
public IEnumerable<Server> ParseUri(string text);
bool CheckServer(Server s);
}

34
Netch/Interops/AioDNS.cs Normal file
View File

@@ -0,0 +1,34 @@
using System.Runtime.InteropServices;
using System.Text;
namespace Netch.Interops
{
public static class AioDNS
{
private const string aiodns_bin = "aiodns.bin";
public static bool Dial(NameList name, string value)
{
Global.Logger.Debug($"[aiodns] Dial {name}: {value}");
return aiodns_dial(name, Encoding.UTF8.GetBytes(value));
}
[DllImport(aiodns_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern bool aiodns_dial(NameList name, byte[] value);
[DllImport(aiodns_bin, EntryPoint = "aiodns_init", CallingConvention = CallingConvention.Cdecl)]
public static extern bool Init();
[DllImport(aiodns_bin, EntryPoint = "aiodns_free", CallingConvention = CallingConvention.Cdecl)]
public static extern void Free();
public enum NameList
{
TYPE_REST,
TYPE_ADDR,
TYPE_LIST,
TYPE_CDNS,
TYPE_ODNS
}
}
}

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

@@ -0,0 +1,78 @@
using System.Runtime.InteropServices;
namespace Netch.Interops
{
public static class Redirector
{
public enum NameList
{
TYPE_FILTERLOOPBACK,
TYPE_FILTERICMP,
TYPE_FILTERTCP,
TYPE_FILTERUDP,
TYPE_CLRNAME,
TYPE_ADDNAME,
TYPE_BYPNAME,
TYPE_DNSHOST,
TYPE_TCPLISN,
TYPE_TCPTYPE,
TYPE_TCPHOST,
TYPE_TCPUSER,
TYPE_TCPPASS,
TYPE_TCPMETH,
TYPE_TCPPROT,
TYPE_TCPPRPA,
TYPE_TCPOBFS,
TYPE_TCPOBPA,
TYPE_UDPLISN,
TYPE_UDPTYPE,
TYPE_UDPHOST,
TYPE_UDPUSER,
TYPE_UDPPASS,
TYPE_UDPMETH,
TYPE_UDPPROT,
TYPE_UDPPRPA,
TYPE_UDPOBFS,
TYPE_UDPOBPA
}
public static bool Dial(NameList name, string value)
{
Global.Logger.Debug($"[Redirector] Dial {name}: {value}");
return aio_dial(name, value);
}
public static bool Init()
{
return aio_init();
}
public static bool Free()
{
return aio_free();
}
public const int UdpNameListOffset = (int)NameList.TYPE_UDPLISN - (int)NameList.TYPE_TCPLISN;
private const string Redirector_bin = "Redirector.bin";
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern bool aio_dial(NameList name, [MarshalAs(UnmanagedType.LPWStr)] string value);
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern bool aio_init();
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern bool aio_free();
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern ulong aio_getUP();
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern ulong aio_getDL();
}
}

View File

@@ -0,0 +1,26 @@
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Netch.Interops
{
public static class RouteHelper
{
[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

@@ -0,0 +1,73 @@
using System.Runtime.InteropServices;
using System.Text;
namespace Netch.Interops
{
public static class tun2socks
{
public enum NameList
{
TYPE_BYPBIND,
TYPE_BYPLIST,
TYPE_DNSADDR,
TYPE_ADAPMTU,
TYPE_TCPREST,
TYPE_TCPTYPE,
TYPE_TCPHOST,
TYPE_TCPUSER,
TYPE_TCPPASS,
TYPE_TCPMETH,
TYPE_TCPPROT,
TYPE_TCPPRPA,
TYPE_TCPOBFS,
TYPE_TCPOBPA,
TYPE_UDPREST,
TYPE_UDPTYPE,
TYPE_UDPHOST,
TYPE_UDPUSER,
TYPE_UDPPASS,
TYPE_UDPMETH,
TYPE_UDPPROT,
TYPE_UDPPRPA,
TYPE_UDPOBFS,
TYPE_UDPOBPA
}
public static bool Dial(NameList name, string value)
{
Global.Logger.Debug($"[tun2socks] Dial {name}: {value}");
return tun_dial(name, Encoding.UTF8.GetBytes(value));
}
public static bool Init()
{
Global.Logger.Debug($"[tun2socks] init");
return tun_init();
}
public static bool Free()
{
return tun_free();
}
private const string tun2socks_bin = "tun2socks.bin";
[DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern bool tun_dial(NameList name, byte[] value);
[DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern bool tun_init();
[DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern bool tun_free();
[DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern ulong tun_luid();
[DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern ulong tun_getUP();
[DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern ulong tun_getDL();
}
}

View File

@@ -1,21 +1,34 @@
using System;
#nullable disable
using System;
namespace Netch.Models.GitHubRelease
{
public class Asset
{
public string url { get; set; }
public int id { get; set; }
public string node_id { get; set; }
public string name { get; set; }
public object label { get; set; }
public GitHubUser uploader { get; set; }
public string content_type { get; set; }
public string state { get; set; }
public int size { get; set; }
public int download_count { get; set; }
public DateTime created_at { get; set; }
public DateTime updated_at { get; set; }
public string browser_download_url { get; set; }
}
}

View File

@@ -5,12 +5,12 @@
private readonly string _owner;
private readonly string _repo;
public string AllReleaseUrl => $@"https://api.github.com/repos/{_owner}/{_repo}/releases";
public GitHubRelease(string owner, string repo)
{
_owner = owner;
_repo = repo;
}
public string AllReleaseUrl => $@"https://api.github.com/repos/{_owner}/{_repo}/releases";
}
}
}

View File

@@ -1,24 +1,42 @@
namespace Netch.Models.GitHubRelease
#nullable disable
namespace Netch.Models.GitHubRelease
{
public class GitHubUser
{
public string login { get; set; }
public int id { get; set; }
public string node_id { get; set; }
public string avatar_url { get; set; }
public string gravatar_id { get; set; }
public string url { get; set; }
public string html_url { get; set; }
public string followers_url { get; set; }
public string following_url { get; set; }
public string gists_url { get; set; }
public string starred_url { get; set; }
public string subscriptions_url { get; set; }
public string organizations_url { get; set; }
public string repos_url { get; set; }
public string events_url { get; set; }
public string received_events_url { get; set; }
public string type { get; set; }
public bool site_admin { get; set; }
}
}

View File

@@ -1,26 +1,44 @@
using System;
#nullable disable
using System;
namespace Netch.Models.GitHubRelease
{
public class Release
{
public string url { get; set; }
public string assets_url { get; set; }
public string upload_url { get; set; }
public string html_url { get; set; }
public int id { get; set; }
public string node_id { get; set; }
public string tag_name { get; set; }
public string target_commitish { get; set; }
public string name { get; set; }
public bool draft { get; set; }
public GitHubUser author { get; set; }
public bool prerelease { get; set; }
public DateTime created_at { get; set; }
public DateTime published_at { get; set; }
public Asset[] assets { get; set; }
public string tarball_url { get; set; }
public string zipball_url { get; set; }
public string body { get; set; }
}
}

View File

@@ -1,60 +1,61 @@
using System;
using System.Text;
using System.Linq;
using System.Text.RegularExpressions;
namespace Netch.Models.GitHubRelease
{
[Serializable]
public struct SuffixVersion : ICloneable, IComparable, IComparable<SuffixVersion>, IEquatable<SuffixVersion>
public struct SuffixVersion : IComparable, IComparable<SuffixVersion>
{
public int Major { get; }
public int Minor { get; }
public int Patch { get; }
public string PreRelease { get; }
public int Build { get; }
public Version Version { get; }
public SuffixVersion(int major, int minor, int patch, string preRelease, int build)
public string? Suffix { get; }
public int SuffixNum { get; }
private SuffixVersion(Version version)
{
Major = major;
Minor = minor;
Patch = patch;
PreRelease = preRelease;
Build = build;
Version = version;
Suffix = null;
SuffixNum = 0;
}
public SuffixVersion(Version version, string preRelease, int build)
private SuffixVersion(Version version, string suffix, int suffixNum)
{
Major = version.Major;
Minor = version.Minor;
Patch = version.Build;
PreRelease = preRelease;
Build = build;
Version = version;
Suffix = suffix;
SuffixNum = suffixNum;
}
public static SuffixVersion Parse(string input)
public static SuffixVersion Parse(string? value)
{
var splitStr = input.Split('-');
var dotNetVersion = Version.Parse(splitStr[0]);
var preRelease = new StringBuilder();
var build = 0;
if (value == null)
throw new ArgumentNullException(nameof(value));
if (splitStr.Length > 1)
foreach (var c in splitStr[1])
var strings = value.Split('-');
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:
{
if (int.TryParse(c.ToString(), out var n))
{
build = build * 10 + n;
}
else
{
preRelease.Append(c);
}
}
var match = Regex.Match(suffix, @"(?<suffix>\D+)(?<num>\d+)");
if (!match.Success)
throw new Exception();
return new SuffixVersion(dotNetVersion, preRelease.ToString(), build);
return new SuffixVersion(version, match.Groups["suffix"].Value, int.Parse(match.Groups["num"].Value));
}
}
}
public static bool TryParse(string input, out SuffixVersion result)
public static bool TryParse(string? input, out SuffixVersion result)
{
result = default;
try
{
result = Parse(input);
@@ -62,76 +63,48 @@ namespace Netch.Models.GitHubRelease
}
catch (Exception)
{
result = default;
return false;
}
}
public object Clone() => new SuffixVersion(Major, Major, Patch, PreRelease, Build);
public int CompareTo(object obj)
public int CompareTo(object? obj)
{
if (obj is SuffixVersion version)
return CompareTo(version);
return -1;
if (obj is not SuffixVersion version)
throw new ArgumentOutOfRangeException();
return CompareTo(version);
}
/// <summary>
///
/// </summary>
/// <param name="other"></param>
/// <returns>
/// greater than 0 newer
/// greater than 0 newer
/// </returns>
public int CompareTo(SuffixVersion other)
{
var majorComparison = Major.CompareTo(other.Major);
if (majorComparison != 0)
return majorComparison;
var minorComparison = Minor.CompareTo(other.Minor);
if (minorComparison != 0)
return minorComparison;
var patchComparison = Patch.CompareTo(other.Patch);
if (patchComparison != 0)
return patchComparison;
if (PreRelease == string.Empty)
return other.PreRelease == string.Empty ? 0 : 1;
if (other.PreRelease == string.Empty)
return -1;
var suffixComparison = string.Compare(PreRelease, other.PreRelease, StringComparison.Ordinal);
var versionComparison = Version.CompareTo(other.Version);
if (versionComparison != 0)
return versionComparison;
var suffixExistComparison = (Suffix == null ? 1 : 0) - (other.Suffix == null ? 1 : 0);
if (suffixExistComparison != 0)
return suffixExistComparison;
var suffixComparison = string.Compare(Suffix, other.Suffix, StringComparison.OrdinalIgnoreCase);
if (suffixComparison != 0)
return suffixComparison;
return Build.CompareTo(other.Build);
}
public bool Equals(SuffixVersion other)
{
return Major == other.Major && Minor == other.Minor && Patch == other.Patch && PreRelease == other.PreRelease && Build == other.Build;
}
public override bool Equals(object obj)
{
return obj is SuffixVersion other && Equals(other);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = Major;
hashCode = (hashCode * 397) ^ Minor;
hashCode = (hashCode * 397) ^ Patch;
hashCode = (hashCode * 397) ^ (PreRelease != null ? PreRelease.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ Build;
return hashCode;
}
return SuffixNum - other.SuffixNum;
}
public override string ToString()
{
return $"{Major}.{Minor}.{Patch}{(string.IsNullOrEmpty(PreRelease) ? "" : "-")}{PreRelease}{(Build == 0 ? "" : Build.ToString())}";
var s = Version.ToString();
if (Suffix != null)
s += $"-{Suffix}{SuffixNum}";
return s;
}
}
}

View File

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

View File

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

View File

@@ -4,6 +4,7 @@ namespace Netch.Models
{
INFO,
WARNING,
ERROR
ERROR,
DEBUG
}
}

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

@@ -0,0 +1,15 @@
using System;
namespace Netch.Models
{
public class MessageException : Exception
{
public MessageException()
{
}
public MessageException(string message) : base(message)
{
}
}
}

View File

@@ -1,131 +1,147 @@
using System.Collections.Generic;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Netch.Utils;
using Netch.Enums;
namespace Netch.Models
{
public class Mode
{
/// <summary>
/// 备注
///
/// </summary>
public string Remark;
/// <param name="fullName">Mode File FullPath</param>
/// <exception cref="FormatException"></exception>
/// <exception cref="NotSupportedException"></exception>
public Mode(string? fullName)
{
FullName = fullName;
if (FullName == null || !File.Exists(FullName))
return;
(Remark, Type) = ReadHead(FullName);
}
public string? FullName { get; }
/// <summary>
/// 规则
/// </summary>
public List<string> Content => _content ??= ReadContent();
private List<string>? _content;
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; } = "";
public ModeType Type { get; set; } = ModeType.Process;
/// <summary>
/// 文件相对路径(必须是存在的文件)
/// </summary>
public string RelativePath;
public string? RelativePath => FullName == null ? null : ModeHelper.GetRelativePath(FullName);
/// <summary>
/// 无后缀文件名
/// </summary>
public string FileName;
/// <summary>
/// 类型<para />
/// 0. Socks5 + 进程加速<para />
/// 1. Socks5 + TUN/TAP 规则内 IP CIDR 加速<para />
/// 2. Socks5 + TUN/TAP 全局,绕过规则内 IP CIDR<para />
/// 3. Socks5 + HTTP 代理(设置到系统代理)<para />
/// 4. Socks5 代理(不设置到系统代理)<para />
/// 5. Socks5 + HTTP 代理(不设置到系统代理)<para />
/// </summary>
public int Type = 0;
/// <summary>
/// 绕过中国0. 不绕过 1. 绕过)
/// </summary>
public bool BypassChina = false;
/// <summary>
/// 规则
/// </summary>
public readonly List<string> Rule = new List<string>();
public List<string> FullRule
public IEnumerable<string> GetRules()
{
get
var result = new List<string>();
foreach (var s in Content)
{
var result = new List<string>();
foreach (var s in Rule)
if (string.IsNullOrWhiteSpace(s))
continue;
if (s.StartsWith("//"))
continue;
const string include = "#include";
if (s.StartsWith(include))
{
if (string.IsNullOrWhiteSpace(s))
continue;
if (s.StartsWith("//"))
continue;
var relativePath = new StringBuilder(s[include.Length..].Trim());
relativePath.Replace("<", "").Replace(">", "");
relativePath.Replace(".h", ".txt");
if (s.StartsWith("#include"))
{
var relativePath = new StringBuilder(s.Substring(8).Trim());
relativePath.Replace("<", "");
relativePath.Replace(">", "");
relativePath.Replace(".h", ".txt");
var mode = Global.Modes.FirstOrDefault(m => m.RelativePath?.Equals(relativePath.ToString()) ?? false) ??
throw new MessageException($"{relativePath} file included in {Remark} not found");
var mode = Global.Modes.FirstOrDefault(m => m.RelativePath.Equals(relativePath.ToString()));
if (mode == this)
throw new MessageException("Can't self-reference");
if (mode == null)
{
Logging.Warning($"{relativePath} file included in {Remark} not found");
}
else if (mode == this)
{
Logging.Warning("Can't self-reference");
}
else
{
if (mode.Type != Type)
{
Logging.Warning($"{mode.Remark}'s mode is not as same as {Remark}'s mode");
}
else
{
if (mode.Rule.Any(rule => rule.StartsWith("#include")))
{
Logging.Warning("Cannot reference mode that reference other mode");
}
else
{
result.AddRange(mode.FullRule);
}
}
}
}
else
{
result.Add(s);
}
if (mode.Type != Type)
throw new MessageException($"{mode.Remark}'s mode is not as same as {Remark}'s mode");
if (mode.Content.Any(rule => rule.StartsWith(include)))
throw new Exception("Cannot reference mode that reference other mode");
result.AddRange(mode.GetRules());
}
else
{
result.Add(s);
}
return result;
}
return result;
}
private static (string, ModeType) ReadHead(string fileName)
{
var text = File.ReadLines(fileName).First();
if (text.First() != '#')
throw new FormatException($"{fileName} head not found at Line 0");
var split = text[1..].SplitTrimEntries(',');
var typeNumber = int.TryParse(split.ElementAtOrDefault(1), out var type) ? type : 0;
if (!Enum.GetValues(typeof(ModeType)).Cast<int>().Contains(typeNumber))
throw new NotSupportedException($"Not support mode \"{typeNumber}\".");
return (split[0], (ModeType)typeNumber);
}
private List<string> ReadContent()
{
if (FullName == null || !File.Exists(FullName))
return new List<string>();
return File.ReadLines(FullName).Skip(1).ToList();
}
public void ResetContent()
{
_content = null;
}
public void WriteFile()
{
var dir = Path.GetDirectoryName(FullName)!;
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
var content = $"# {Remark}, {(int)Type}{Constants.EOF}{string.Join(Constants.EOF, Content)}";
// 写入到模式文件里
File.WriteAllText(FullName!, content);
}
/// <summary>
/// 获取备注
/// 获取备注
/// </summary>
/// <returns>备注</returns>
public override string ToString()
{
return $"[{Type + 1}] {i18N.Translate(Remark)}";
}
/// <summary>
/// 获取模式文件字符串
/// </summary>
/// <returns>模式文件字符串</returns>
public string ToFileString()
{
return $"# {Remark}, {Type}, {(BypassChina ? 1 : 0)}{Global.EOF}{string.Join(Global.EOF, Rule)}";
return $"[{(int)Type + 1}] {i18N.Translate(Remark)}";
}
}
public static class ModeExtension
{
/// 是否会转发 UDP
public static bool TestNatRequired(this Mode mode) => mode.Type is 0 or 1 or 2;
/// Socks5 分流是否能被有效实施
public static bool ClientRouting(this Mode mode) => mode.Type is not (1 or 2);
/// 是否会转发 UDP
public static bool TestNatRequired(this Mode mode)
{
return mode.Type is ModeType.Process or ModeType.BypassRuleIPs;
}
}
}

50
Netch/Models/NetRoute.cs Normal file
View File

@@ -0,0 +1,50 @@
using System;
using System.Net;
using Vanara.PInvoke;
namespace Netch.Models
{
public struct NetRoute
{
public static NetRoute TemplateBuilder(string gateway, int interfaceIndex, int metric = 0)
{
return new()
{
Gateway = gateway,
InterfaceIndex = interfaceIndex,
Metric = metric
};
}
public static (NetRoute, IPAddress address) GetBestRouteTemplate()
{
if (IpHlpApi.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var route) != 0)
throw new MessageException("GetBestRoute 搜索失败");
var address = new IPAddress(route.dwForwardNextHop.S_addr);
var gateway = new IPAddress(route.dwForwardNextHop.S_un_b);
return (TemplateBuilder(gateway.ToString(), (int)route.dwForwardIfIndex), address);
}
public int InterfaceIndex;
public string Gateway;
public string Network;
public byte Cidr;
public int Metric;
public NetRoute FillTemplate(string network, byte cidr, int? metric = null)
{
var o = (NetRoute)MemberwiseClone();
o.Network = network;
o.Cidr = cidr;
if (metric != null)
o.Metric = (int)metric;
return o;
}
}
}

View File

@@ -0,0 +1,20 @@
namespace Netch.Models
{
public readonly struct NumberRange
{
public int Start { get; }
public int End { get; }
public NumberRange(int start, int end)
{
Start = start;
End = end;
}
public bool InRange(int num)
{
return Start <= num && num <= End;
}
}
}

View File

@@ -0,0 +1,120 @@
using System;
using System.Linq;
using System.Reflection;
namespace Netch.Models
{
public abstract class ParameterBase
{
// null value par
private readonly bool _full;
protected readonly string ParametersSeparate = " ";
protected readonly string Separate = " ";
protected readonly string VerbPrefix = "-";
protected readonly string FullPrefix = "--";
protected ParameterBase()
{
_full = !GetType().IsDefined(typeof(VerbAttribute));
}
public override string ToString()
{
var parameters = GetType().GetProperties().Select(PropToParameter).Where(s => s != null).Cast<string>();
return string.Join(ParametersSeparate, parameters).Trim();
}
private string? PropToParameter(PropertyInfo p)
{
// prefix
bool full;
if (p.IsDefined(typeof(VerbAttribute)))
full = false;
else if (p.IsDefined(typeof(FullAttribute)))
full = true;
else
full = _full;
var prefix = full ? FullPrefix : VerbPrefix;
// key
var key = p.GetCustomAttribute<RealNameAttribute>()?.Name ?? p.Name;
// build
var value = p.GetValue(this);
switch (value)
{
case bool b:
return b ? $"{prefix}{key}" : null;
default:
if (string.IsNullOrWhiteSpace(value?.ToString()))
return p.IsDefined(typeof(OptionalAttribute)) ? null : throw new RequiredArgumentValueInvalidException(p.Name, this, null);
if (p.IsDefined(typeof(QuoteAttribute)))
value = $"\"{value}\"";
return $"{prefix}{key}{Separate}{value}";
}
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
public class VerbAttribute : Attribute
{
// Don't use verb and full both on one class or property
// if you did, will take verb
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
public class FullAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class OptionalAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class QuoteAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class RealNameAttribute : Attribute
{
public string Name { get; }
public RealNameAttribute(string name)
{
Name = name;
}
}
[Serializable]
public class RequiredArgumentValueInvalidException : Exception
{
public string? ArgumentName { get; }
public object? ArgumentObject { get; }
private readonly string? _message;
private const string DefaultMessage = "{0}'s Argument \"{1}\" value invalid. A required argument's value can't be null or empty.";
public override string Message => _message ?? string.Format(DefaultMessage, ArgumentObject!.GetType(), ArgumentName);
public RequiredArgumentValueInvalidException()
{
_message = "Some Argument value invalid. A required argument value's can't be null or empty.";
}
public RequiredArgumentValueInvalidException(string argumentName, object argumentObject, string? message)
{
ArgumentName = argumentName;
ArgumentObject = argumentObject;
_message = message;
}
}
}

View File

@@ -2,27 +2,28 @@
{
public class Profile
{
public string ServerRemark;
public string ModeRemark;
public string ProfileName;
public int Index { get; set; }
public bool IsDummy = true;
public string ModeRemark { get; set; }
public Profile(Server server, Mode mode, string name)
public string ProfileName { get; set; }
public string ServerRemark { get; set; }
public Profile(Server server, Mode mode, string name, int index)
{
ServerRemark = server.Remark;
ModeRemark = mode.Remark;
ProfileName = name;
IsDummy = false;
Index = index;
}
/// <summary>
/// Return a dummy one.
/// </summary>
public Profile()
{
ServerRemark = string.Empty;
ModeRemark = string.Empty;
ProfileName = string.Empty;
Index = 0;
}
}
}
}

View File

@@ -1,48 +1,60 @@
using System;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Netch.Utils;
namespace Netch.Models
{
public class Server : ICloneable
{
/// <summary>
/// 备注
/// 延迟
/// </summary>
public string Remark;
[JsonIgnore]
public int Delay { get; private set; } = -1;
/// <summary>
/// 组
/// </summary>
public string Group = "None";
/// <summary>
/// 代理类型
/// </summary>
public string Type;
/// <summary>
/// 倍率
/// </summary>
public double Rate = 1.0;
public string Group { get; set; } = "None";
/// <summary>
/// 地址
/// </summary>
public string Hostname;
public string Hostname { get; set; } = string.Empty;
/// <summary>
/// 端口
/// </summary>
public ushort Port;
public ushort Port { get; set; }
/// <summary>
/// 延迟
/// 倍率
/// </summary>
public int Delay = -1;
public double Rate { get; } = 1.0;
/// <summary>
/// 获取备注
/// 备注
/// </summary>
public string Remark { get; set; } = "";
/// <summary>
/// 代理类型
/// </summary>
public virtual string Type { get; } = string.Empty;
[JsonExtensionData]
// ReSharper disable once CollectionNeverUpdated.Global
public Dictionary<string, object> ExtensionData { get; set; } = new();
public object Clone()
{
return MemberwiseClone();
}
/// <summary>
/// 获取备注
/// </summary>
/// <returns>备注</returns>
public override string ToString()
@@ -52,43 +64,46 @@ namespace Netch.Models
if (Group.Equals("None") || Group.Equals(""))
Group = "NONE";
return $"[{ServerHelper.GetUtilByTypeName(Type)?.ShortName ?? "WTF"}][{Group}] {remark}";
}
string shortName;
if (Type == string.Empty)
{
shortName = "WTF";
}
else
{
shortName = ServerHelper.GetUtilByTypeName(Type).ShortName;
}
public object Clone()
{
return MemberwiseClone();
return $"[{shortName}][{Group}] {remark}";
}
/// <summary>
/// 测试延迟
/// 测试延迟
/// </summary>
/// <returns>延迟</returns>
public int Test()
{
try
{
var destination = DNS.Lookup(Hostname);
var destination = DnsUtils.Lookup(Hostname);
if (destination == null)
{
return Delay = -2;
}
var list = new Task<int>[3];
for (var i = 0; i < 3; i++)
{
list[i] = Task.Run(async () =>
{
try
{
return Global.Settings.ServerTCPing ? await Utils.Utils.TCPingAsync(destination, Port) : await Utils.Utils.ICMPing(destination, Port);
return Global.Settings.ServerTCPing
? await Utils.Utils.TCPingAsync(destination, Port)
: Utils.Utils.ICMPing(destination, Port);
}
catch (Exception)
{
return -4;
}
});
}
Task.WaitAll(list[0], list[1], list[2]);
@@ -107,7 +122,20 @@ namespace Netch.Models
{
public static string AutoResolveHostname(this Server server)
{
return Global.Settings.ResolveServerHostname ? DNS.Lookup(server.Hostname).ToString() : server.Hostname;
return Global.Settings.ResolveServerHostname ? DnsUtils.Lookup(server.Hostname)!.ToString() : server.Hostname;
}
public static bool Valid(this Server server)
{
try
{
ServerHelper.GetTypeByTypeName(server.Type);
return true;
}
catch
{
return false;
}
}
}
}

View File

@@ -1,81 +1,118 @@
using System.Collections.Generic;
using Netch.Utils;
using System.Collections.Generic;
namespace Netch.Models
{
/// <summary>
/// TUN/TAP 适配器配置类
/// </summary>
public class TUNTAPConfig
public class TUNConfig
{
/// <summary>
/// 地址
/// </summary>
public string Address = "10.0.236.10";
public string Address { get; set; } = "10.0.236.10";
/// <summary>
/// DNS
/// </summary>
public List<string> DNS = new();
public string HijackDNS { get; set; } = "tcp://1.1.1.1:53";
/// <summary>
/// 网关
/// </summary>
public string Gateway = "10.0.236.1";
public string Gateway { get; set; } = "10.0.236.1";
/// <summary>
/// 掩码
/// </summary>
public string Netmask = "255.255.255.0";
public string Netmask { get; set; } = "255.255.255.0";
/// <summary>
/// 模式 2 下是否代理 DNS
/// </summary>
public bool ProxyDNS = false;
public bool ProxyDNS { get; set; } = false;
/// <summary>
/// 使用自定义 DNS 设置
/// </summary>
public bool UseCustomDNS = false;
public bool UseCustomDNS { get; set; } = true;
/// <summary>
/// 使用Fake DNS
/// 全局绕过 IP 列表
/// </summary>
public bool UseFakeDNS = false;
public List<string> BypassIPs { get; set; } = new();
}
public class KcpConfig
{
public bool congestion = false;
public bool congestion { get; set; } = false;
public int downlinkCapacity = 100;
public int mtu = 1350;
public int downlinkCapacity { get; set; } = 100;
public int readBufferSize = 2;
public int mtu { get; set; } = 1350;
public int tti = 50;
public int readBufferSize { get; set; } = 2;
public int uplinkCapacity = 12;
public int tti { get; set; } = 50;
public int writeBufferSize = 2;
public int uplinkCapacity { get; set; } = 12;
public int writeBufferSize { get; set; } = 2;
}
public class V2rayConfig
{
public bool AllowInsecure = true;
public bool AllowInsecure { get; set; } = false;
public KcpConfig KcpConfig = new();
public KcpConfig KcpConfig { get; set; } = new();
public bool UseMux = false;
public bool UseMux { get; set; } = false;
public bool V2rayNShareLink { get; set; } = true;
public bool XrayCone { get; set; } = false;
}
public class AioDNSConfig
{
public string ChinaDNS = "223.5.5.5";
public string ChinaDNS { get; set; } = "tcp://223.5.5.5:53";
public string OtherDNS = "1.1.1.1";
public string OtherDNS { get; set; } = "tcp://1.1.1.1:53";
public string Protocol = "tcp";
public string RulePath = "bin\\china_site_list";
public ushort ListenPort { get; set; } = 253;
}
public class RedirectorConfig
{
/// <summary>
/// 不代理TCP
/// </summary>
public PortType ProxyProtocol { get; set; } = PortType.Both;
/// <summary>
/// 是否开启DNS转发
/// </summary>
public bool DNSHijack { get; set; } = true;
/// <summary>
/// 转发DNS地址
/// </summary>
public string DNSHijackHost { get; set; } = "1.1.1.1:53";
public string ICMPHost { get; set; } = "1.2.4.8";
public bool ICMPHijack { get; set; } = false;
/// <summary>
/// 是否使用RDR内置SS
/// </summary>
public bool RedirectorSS { get; set; } = false;
/// <summary>
/// 是否代理子进程
/// </summary>
public bool ChildProcessHandle { get; set; } = false;
}
/// <summary>
@@ -83,208 +120,156 @@ namespace Netch.Models
/// </summary>
public class Setting
{
public RedirectorConfig Redirector { get; set; } = new();
/// <summary>
/// 服务器列表
/// </summary>
public readonly List<Server> Server = new();
public List<Server> Server { get; set; } = new();
/// <summary>
/// ACL规则
/// </summary>
public string ACL = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/banAD.acl";
public AioDNSConfig AioDNS = new();
/// <summary>
/// 是否使用DLL启动Shadowsocks
/// </summary>
public bool BootShadowsocksFromDLL = true;
/// <summary>
/// 全局绕过 IP 列表
/// </summary>
public List<string> BypassIPs = new();
public AioDNSConfig AioDNS { get; set; } = new();
/// <summary>
/// 是否检查 Beta 更新
/// </summary>
public bool CheckBetaUpdate = false;
public bool CheckBetaUpdate { get; set; } = false;
/// <summary>
/// 是否打开软件时检查更新
/// </summary>
public bool CheckUpdateWhenOpened = true;
public bool CheckUpdateWhenOpened { get; set; } = true;
/// <summary>
/// 测试所有服务器心跳/秒
/// </summary>
public int DetectionTick = 10;
public int DetectionTick { get; set; } = 10;
/// <summary>
/// 是否关闭窗口时退出
/// </summary>
public bool ExitWhenClosed = false;
public bool ExitWhenClosed { get; set; } = false;
/// <summary>
/// HTTP 本地端口
/// </summary>
public ushort HTTPLocalPort = 2802;
public ushort HTTPLocalPort { get; set; } = 2802;
/// <summary>
/// 语言设置
/// </summary>
public string Language = "System";
public string Language { get; set; } = "System";
/// <summary>
/// HTTP 和 Socks5 本地代理地址
/// </summary>
public string LocalAddress = "127.0.0.1";
public string LocalAddress { get; set; } = "127.0.0.1";
/// <summary>
/// 是否启动后自动最小化
/// </summary>
public bool MinimizeWhenStarted = false;
public bool MinimizeWhenStarted { get; set; } = false;
/// <summary>
/// 模式选择位置
/// </summary>
public int ModeComboBoxSelectedIndex = 0;
/// <summary>
/// 要修改为的系统 DNS
/// </summary>
public string ModifiedDNS = "1.1.1.1,8.8.8.8";
/// <summary>
/// 修改系统 DNS
/// </summary>
public bool ModifySystemDNS = false;
/// <summary>
/// GFWList
/// </summary>
public string PAC = "https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_white.pac";
/// <summary>
/// PAC端口
/// </summary>
public int Pac_Port = 2803;
/// <summary>
/// PAC URL
/// </summary>
public string Pac_Url = "";
/// <summary>
/// 不代理TCP
/// </summary>
public bool ProcessNoProxyForTcp = false;
/// <summary>
/// 不代理UDP
/// </summary>
public bool ProcessNoProxyForUdp = false;
public int ModeComboBoxSelectedIndex { get; set; } = -1;
/// <summary>
/// 快捷配置数量
/// </summary>
public int ProfileCount = 4;
public int ProfileCount { get; set; } = 4;
/// <summary>
/// 已保存的快捷配置
/// </summary>
public List<Profile> Profiles = new();
public List<Profile> Profiles { get; set; } = new();
/// <summary>
/// 是否使用RDR内置SS
/// 配置最大列数
/// </summary>
public bool RedirectorSS = false;
/// <summary>
/// Redirector TCP 占用端口
/// </summary>
public ushort RedirectorTCPPort = 3901;
public byte ProfileTableColumnCount { get; set; } = 5;
/// <summary>
/// 网页请求超时 毫秒
/// </summary>
public int RequestTimeout = 10000;
public int RequestTimeout { get; set; } = 10000;
/// <summary>
/// 解析服务器主机名
/// </summary>
public bool ResolveServerHostname = false;
public bool ResolveServerHostname { get; set; } = true;
/// <summary>
/// 是否开机启动软件
/// </summary>
public bool RunAtStartup = false;
public bool RunAtStartup { get; set; } = false;
/// <summary>
/// 服务器选择位置
/// </summary>
public int ServerComboBoxSelectedIndex = 0;
public int ServerComboBoxSelectedIndex { get; set; } = -1;
/// <summary>
/// 服务器测试方式 false.ICMPing true.TCPing
/// </summary>
public bool ServerTCPing = true;
public bool ServerTCPing { get; set; } = true;
/// <summary>
/// Socks5 本地端口
/// </summary>
public ushort Socks5LocalPort = 2801;
public ushort Socks5LocalPort { get; set; } = 2801;
/// <summary>
/// 启动后延迟测试间隔/秒
/// </summary>
public int StartedPingInterval = -1;
public int StartedPingInterval { get; set; } = -1;
/// <summary>
/// 是否打开软件时启动加速
/// </summary>
public bool StartWhenOpened = false;
public bool StartWhenOpened { get; set; } = false;
/// <summary>
/// 是否退出时停止
/// </summary>
public bool StopWhenExited = false;
public bool StopWhenExited { get; set; } = false;
/// <summary>
/// STUN测试服务器
/// </summary>
public string STUN_Server = "stun.syncthing.net";
public string STUN_Server { get; set; } = "stun.syncthing.net";
/// <summary>
/// STUN测试服务器
/// </summary>
public int STUN_Server_Port = 3478;
public int STUN_Server_Port { get; set; } = 3478;
/// <summary>
/// 订阅链接列表
/// </summary>
public List<SubscribeLink> SubscribeLink = new();
public List<SubscribeLink> SubscribeLink { get; set; } = new();
/// <summary>
/// TUNTAP 适配器配置
/// </summary>
public TUNTAPConfig TUNTAP = new();
/// <summary>
/// UDP Socket 占用端口
/// </summary>
public ushort UDPSocketPort = 18291;
public TUNConfig TUNTAP { get; set; } = new();
/// <summary>
/// 是否打开软件时更新订阅
/// </summary>
public bool UpdateServersWhenOpened = false;
public bool UpdateServersWhenOpened { get; set; } = false;
/// <summary>
/// 使用代理更新订阅
/// </summary>
public bool UseProxyToUpdateSubscription = false;
public V2rayConfig V2RayConfig { get; set; } = new();
public V2rayConfig V2RayConfig = new();
public Setting Clone()
{
return (Setting)MemberwiseClone();
}
public void Set(Setting value)
{
foreach (var p in typeof(Setting).GetProperties())
p.SetValue(this, p.GetValue(value));
}
}
}

View File

@@ -30,7 +30,6 @@
/// </summary>
Stopped,
/// <summary>
/// 退出中
/// </summary>
@@ -43,6 +42,7 @@
{
if (state == State.Waiting)
return "Waiting for command";
return state.ToString();
}
}

View File

@@ -0,0 +1,52 @@
using Netch.Utils;
using System.Collections.Generic;
using System.Linq;
namespace Netch.Models
{
public static class StatusPortInfoText
{
private static ushort? _socks5Port;
private static ushort? _httpPort;
private static bool _shareLan;
public static ushort HttpPort
{
set => _httpPort = value;
}
public static ushort Socks5Port
{
set => _socks5Port = value;
}
public static string Value
{
get
{
var strings = new List<string>();
if (_socks5Port != null)
strings.Add($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}");
if (_httpPort != null)
strings.Add($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}");
if (!strings.Any())
return string.Empty;
return $" ({(_shareLan ? i18N.Translate("Allow other Devices to connect") + " " : "")}{string.Join(" | ", strings)})";
}
}
public static void UpdateShareLan()
{
_shareLan = Global.Settings.LocalAddress != "127.0.0.1";
}
public static void Reset()
{
_httpPort = _socks5Port = null;
}
}
}

View File

@@ -5,21 +5,21 @@
/// <summary>
/// 启用状态
/// </summary>
public bool Enable = true;
/// <summary>
/// 备注
/// </summary>
public string Remark;
public bool Enable { get; set; } = true;
/// <summary>
/// 链接
/// </summary>
public string Link;
public string Link { get; set; } = string.Empty;
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; } = string.Empty;
/// <summary>
/// User Agent
/// </summary>
public string UserAgent;
public string UserAgent { get; set; } = string.Empty;
}
}

19
Netch/Models/TagItem.cs Normal file
View File

@@ -0,0 +1,19 @@
using Netch.Utils;
namespace Netch.Models
{
internal class TagItem<T>
{
private readonly string _text;
public TagItem(T value, string text)
{
_text = text;
Value = value;
}
public string Text => i18N.Translate(_text);
public T Value { get; }
}
}

View File

@@ -1,114 +0,0 @@
using System;
using NETCONLib;
namespace Netch.Models.WinFW
{
public class NetworkConnection : INetConnection, INetConnectionProps, INetSharingConfiguration
{
private readonly INetConnection _icsConn;
private readonly NetSharingManager _icsMgr;
public NetworkConnection(INetConnection icsConnection)
{
_icsMgr = new NetSharingManagerClass();
_icsConn = icsConnection;
}
public void Connect()
{
_icsConn.Connect();
}
public void Delete()
{
_icsConn.Delete();
}
public void Duplicate(string pszwDuplicateName, out INetConnection ppCon)
{
_icsConn.Duplicate(pszwDuplicateName, out ppCon);
}
public void Disconnect()
{
_icsConn.Disconnect();
}
public void GetProperties(IntPtr ppProps)
{
_icsConn.GetProperties(ppProps);
}
public void Rename(string pszwNewName)
{
_icsConn.Rename(pszwNewName);
}
public void GetUiObjectClassId(out Guid pclsid)
{
_icsConn.GetUiObjectClassId(out pclsid);
}
public uint Characteristics => _icsMgr.NetConnectionProps[_icsConn].Characteristics;
public string DeviceName => _icsMgr.NetConnectionProps[_icsConn].DeviceName;
public string Guid => _icsMgr.NetConnectionProps[_icsConn].Guid;
public tagNETCON_MEDIATYPE MediaType => _icsMgr.NetConnectionProps[_icsConn].MediaType;
public string Name => _icsMgr.NetConnectionProps[_icsConn].Name;
public tagNETCON_STATUS Status => _icsMgr.NetConnectionProps[_icsConn].Status;
public INetSharingPortMapping AddPortMapping(string bstrName, byte ucIPProtocol, ushort usExternalPort,
ushort usInternalPort, uint dwOptions, string bstrTargetNameOrIPAddress, tagICS_TARGETTYPE eTargetType)
{
return _icsMgr.INetSharingConfigurationForINetConnection[_icsConn].AddPortMapping(bstrName,
ucIPProtocol, usExternalPort, usInternalPort, dwOptions, bstrTargetNameOrIPAddress, eTargetType);
}
public void DisableInternetFirewall() => _icsMgr.INetSharingConfigurationForINetConnection[_icsConn].DisableInternetFirewall();
public void DisableSharing()
{
_icsMgr.INetSharingConfigurationForINetConnection[_icsConn].DisableSharing();
}
public void EnableInternetFirewall()
{
_icsMgr.INetSharingConfigurationForINetConnection[_icsConn].EnableInternetFirewall();
}
public void EnableSharing(tagSHARINGCONNECTIONTYPE Type)
{
_icsMgr.INetSharingConfigurationForINetConnection[_icsConn].EnableSharing(Type);
}
public void RemovePortMapping(INetSharingPortMapping pMapping)
{
_icsMgr.INetSharingConfigurationForINetConnection[_icsConn].RemovePortMapping(pMapping);
}
public bool InternetFirewallEnabled =>
_icsMgr.INetSharingConfigurationForINetConnection[_icsConn]
.InternetFirewallEnabled;
public INetSharingPortMappingCollection get_EnumPortMappings(tagSHARINGCONNECTION_ENUM_FLAGS Flags)
{
return _icsMgr.INetSharingConfigurationForINetConnection[_icsConn]
.EnumPortMappings[Flags];
}
public tagSHARINGCONNECTIONTYPE SharingConnectionType =>
_icsMgr.INetSharingConfigurationForINetConnection[_icsConn].SharingConnectionType;
public bool SharingEnabled => _icsMgr.INetSharingConfigurationForINetConnection[_icsConn].SharingEnabled;
public INetSharingConfiguration NetSharingConfigurationForINetConnection()
{
return _icsMgr.INetSharingConfigurationForINetConnection[_icsConn];
}
}
}

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