master a8a088458c59 cached
223 files
1.3 MB
373.2k tokens
1322 symbols
1 requests
Download .txt
Showing preview only (1,407K chars total). Download the full file or copy to clipboard to get everything.
Repository: HMBSbige/ShadowsocksR-Windows
Branch: master
Commit: a8a088458c59
Files: 223
Total size: 1.3 MB

Directory structure:
gitextract_jyjjkvlh/

├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   ├── feature_request.md
│   │   └── other-issue.md
│   ├── renovate.json
│   └── workflows/
│       └── CI.yml
├── .gitignore
├── Build/
│   └── DotNetDllPathPatcher.ps1
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── UnitTest/
│   ├── DnsTest.cs
│   ├── EncryptionTest.cs
│   ├── IPSubnet.cs
│   ├── ServerTest.cs
│   ├── SubscribeTest.cs
│   ├── UnitTest.cs
│   └── UnitTest.csproj
├── build.ps1
├── shadowsocks-csharp/
│   ├── Controller/
│   │   ├── AutoStartup.cs
│   │   ├── FileManager.cs
│   │   ├── HttpRequest/
│   │   │   ├── GfwListUpdater.cs
│   │   │   ├── HttpRequest.cs
│   │   │   ├── UpdateChecker.cs
│   │   │   └── UpdateNode.cs
│   │   ├── Logging.cs
│   │   ├── MainController.cs
│   │   ├── MenuViewController.cs
│   │   ├── Service/
│   │   │   ├── HostDaemon.cs
│   │   │   ├── HostMap.cs
│   │   │   ├── HttpPortForwarder.cs
│   │   │   ├── HttpProxyRunner.cs
│   │   │   ├── Listener.cs
│   │   │   ├── Local.cs
│   │   │   ├── PACDaemon.cs
│   │   │   ├── PACServer.cs
│   │   │   ├── ProtocolResponseDetector.cs
│   │   │   ├── Socks5Forwarder.cs
│   │   │   ├── SpeedTest.cs
│   │   │   └── UpdateSubscribeManager.cs
│   │   └── SystemProxy.cs
│   ├── Data/
│   │   ├── abp.js
│   │   ├── chn_ip.txt
│   │   ├── proxy.pac.txt
│   │   └── user-rule.txt
│   ├── Encryption/
│   │   ├── CircularBuffer/
│   │   │   └── ByteCircularBuffer.cs
│   │   ├── CryptoUtils.cs
│   │   ├── EncryptorBase.cs
│   │   ├── EncryptorFactory.cs
│   │   ├── EncryptorInfo.cs
│   │   ├── Exception/
│   │   │   └── CryptoException.cs
│   │   ├── IEncryptor.cs
│   │   ├── OpenSSL.cs
│   │   ├── Sodium.cs
│   │   └── Stream/
│   │       ├── NoneEncryptor.cs
│   │       ├── StreamEncryptor.cs
│   │       ├── StreamOpenSSLEncryptor.cs
│   │       └── StreamSodiumEncryptor.cs
│   ├── Enums/
│   │   ├── BalanceType.cs
│   │   ├── DnsType.cs
│   │   ├── HttpRequestProxyType.cs
│   │   ├── LogLevel.cs
│   │   ├── PacType.cs
│   │   ├── PortMapType.cs
│   │   ├── ProxyMode.cs
│   │   ├── ProxyRuleMode.cs
│   │   ├── ProxyType.cs
│   │   └── ServerTreeViewType.cs
│   ├── I18N/
│   │   ├── App.en-US.xaml
│   │   ├── App.zh-CN.xaml
│   │   ├── App.zh-TW.xaml
│   │   ├── ConfigWindow.en-US.xaml
│   │   ├── ConfigWindow.zh-CN.xaml
│   │   ├── ConfigWindow.zh-TW.xaml
│   │   ├── DnsSettingWindow.en-US.xaml
│   │   ├── DnsSettingWindow.zh-CN.xaml
│   │   ├── DnsSettingWindow.zh-TW.xaml
│   │   ├── LogWindow.en-US.xaml
│   │   ├── LogWindow.zh-CN.xaml
│   │   ├── LogWindow.zh-TW.xaml
│   │   ├── PortSettingsWindow.en-US.xaml
│   │   ├── PortSettingsWindow.zh-CN.xaml
│   │   ├── PortSettingsWindow.zh-TW.xaml
│   │   ├── ServerLogWindow.en-US.xaml
│   │   ├── ServerLogWindow.zh-CN.xaml
│   │   ├── ServerLogWindow.zh-TW.xaml
│   │   ├── SettingsWindow.en-US.xaml
│   │   ├── SettingsWindow.zh-CN.xaml
│   │   ├── SettingsWindow.zh-TW.xaml
│   │   ├── SubscribeWindow.en-US.xaml
│   │   ├── SubscribeWindow.zh-CN.xaml
│   │   └── SubscribeWindow.zh-TW.xaml
│   ├── Model/
│   │   ├── Configuration.cs
│   │   ├── ConfigurationException.cs
│   │   ├── Connections.cs
│   │   ├── DnsBuffer.cs
│   │   ├── DnsClient.cs
│   │   ├── ErrorLog.cs
│   │   ├── Global.cs
│   │   ├── HostNode.cs
│   │   ├── IPRangeSet.cs
│   │   ├── IPSegment.cs
│   │   ├── LRUCache.cs
│   │   ├── MinSearchTree.cs
│   │   ├── PortMapConfig.cs
│   │   ├── PortMapConfigCache.cs
│   │   ├── Rule.cs
│   │   ├── Server.cs
│   │   ├── ServerSelectStrategy.cs
│   │   ├── ServerSubscribe.cs
│   │   ├── ServerTreeViewModel.cs
│   │   ├── Transfer/
│   │   │   ├── ServerSpeedLog.cs
│   │   │   ├── ServerTrans.cs
│   │   │   ├── ServerTransferTotal.cs
│   │   │   └── TransLog.cs
│   │   ├── UriVisitTime.cs
│   │   └── WindowStatus.cs
│   ├── Obfs/
│   │   ├── AuthAES128SHA1.cs
│   │   ├── AuthAkarin.cs
│   │   ├── AuthAkarin_spec_a.cs
│   │   ├── AuthChain_a.cs
│   │   ├── AuthChain_b.cs
│   │   ├── AuthChain_c.cs
│   │   ├── AuthChain_d.cs
│   │   ├── AuthChain_e.cs
│   │   ├── AuthChain_f.cs
│   │   ├── AuthData.cs
│   │   ├── AuthSHA1.cs
│   │   ├── AuthSHA1V2.cs
│   │   ├── AuthSHA1V4.cs
│   │   ├── HttpSimpleObfs.cs
│   │   ├── IObfs.cs
│   │   ├── ObfsBase.cs
│   │   ├── ObfsException.cs
│   │   ├── ObfsFactory.cs
│   │   ├── Plain.cs
│   │   ├── ProtocolException.cs
│   │   ├── ServerInfo.cs
│   │   ├── TlsAuthData.cs
│   │   ├── TlsTicketAuthObfs.cs
│   │   ├── VerifyData.cs
│   │   ├── VerifyDeflateObfs.cs
│   │   ├── VerifySimpleBase.cs
│   │   └── xorshift128plus.cs
│   ├── Program.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── Proxy/
│   │   ├── CallbackState.cs
│   │   ├── CallbackStatus.cs
│   │   ├── Handler.cs
│   │   ├── HandlerConfig.cs
│   │   ├── HttpParser.cs
│   │   ├── IHandler.cs
│   │   ├── ProxyAuthHandler.cs
│   │   ├── ProxyEncryptSocket.cs
│   │   ├── ProxySocketTun.cs
│   │   └── ProxySocketTunLocal.cs
│   ├── SyncfusionLicenseRegister.bat
│   ├── Util/
│   │   ├── Base64.cs
│   │   ├── CRC.cs
│   │   ├── ColorConvert.cs
│   │   ├── Constants.cs
│   │   ├── I18NUtil.cs
│   │   ├── JsonUtils.cs
│   │   ├── NetUtils/
│   │   │   ├── DnsUtil.cs
│   │   │   ├── IPSubnet.cs
│   │   │   ├── SocketUtil.cs
│   │   │   └── WrappedSocket.cs
│   │   ├── QrCodeUtils.cs
│   │   ├── RNG.cs
│   │   ├── Reg.cs
│   │   ├── Utils.cs
│   │   └── ViewUtils.cs
│   ├── View/
│   │   ├── Controls/
│   │   │   ├── BindablePasswordBox.cs
│   │   │   ├── GridColumnSizerExt.cs
│   │   │   ├── MaskedTextBox.xaml
│   │   │   ├── MaskedTextBox.xaml.cs
│   │   │   ├── NumberUpDown.xaml
│   │   │   └── NumberUpDown.xaml.cs
│   │   ├── DnsSettingWindow.xaml
│   │   ├── DnsSettingWindow.xaml.cs
│   │   ├── LogWindow.xaml
│   │   ├── LogWindow.xaml.cs
│   │   ├── NotifyIconResources.xaml
│   │   ├── PortSettingsWindow.xaml
│   │   ├── PortSettingsWindow.xaml.cs
│   │   ├── QRCodeSplashWindow.xaml
│   │   ├── QRCodeSplashWindow.xaml.cs
│   │   ├── ServerConfigWindow.xaml
│   │   ├── ServerConfigWindow.xaml.cs
│   │   ├── ServerLogWindow.xaml
│   │   ├── ServerLogWindow.xaml.cs
│   │   ├── SettingsWindow.xaml
│   │   ├── SettingsWindow.xaml.cs
│   │   ├── ShowTextWindow.xaml
│   │   ├── ShowTextWindow.xaml.cs
│   │   ├── SubscribeWindow.xaml
│   │   ├── SubscribeWindow.xaml.cs
│   │   └── ValueConverter/
│   │       ├── BalanceTypeEnumConverter.cs
│   │       ├── BooleanToEnabledConverter.cs
│   │       ├── ConnectEmptyToBrushConverter.cs
│   │       ├── ConnectErrorToBrushConverter.cs
│   │       ├── ConnectNumberToBrushConverter.cs
│   │       ├── ErrorPercentToBrushConverter.cs
│   │       ├── LatencyToBrushConverter.cs
│   │       ├── ProxyTypeConverter.cs
│   │       ├── ProxyTypeEnumConverter.cs
│   │       ├── ServerTreeTypeToFontConverter.cs
│   │       ├── SpeedToBrushConverter.cs
│   │       ├── TotalDownloadBackgroundBrushConvert.cs
│   │       ├── TotalDownloadRawBackgroundBrushConvert.cs
│   │       ├── TotalUploadBackgroundBrushConvert.cs
│   │       └── UnixSecondsToString.cs
│   ├── ViewModel/
│   │   ├── DnsSettingViewModel.cs
│   │   ├── ServerConfigViewModel.cs
│   │   ├── ServerLogViewModel.cs
│   │   ├── SettingViewModel.cs
│   │   ├── SubscribeWindowViewModel.cs
│   │   └── ViewModelBase.cs
│   └── shadowsocksr.csproj
└── shadowsocks-csharp.sln

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# 如果要从更高级别的目录继承 .editorconfig 设置,请删除以下行
root = true

[*]
# 字符集
charset = utf-8

# 缩进和间距
indent_style = space
indent_size = 4

# 新行首选项
end_of_line = crlf
insert_final_newline = true

[*.bat]
indent_style = tab

[*.csproj]
indent_size = 2

# c# 文件
[*.cs]

# 缩进和间距
indent_style = space

#### .NET 编码约定 ####

# 组织 Using
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
file_header_template = unset

# this. 和 Me. 首选项
dotnet_style_qualification_for_event = false:warning
dotnet_style_qualification_for_field = false:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_property = false:warning

# 语言关键字与 bcl 类型首选项
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
dotnet_style_predefined_type_for_member_access = true:warning

# 括号首选项
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:silent
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:silent

# 修饰符首选项
dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning

# 表达式级首选项
dotnet_style_coalesce_expression = true:warning
dotnet_style_collection_initializer = true:warning
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_null_propagation = true:warning
dotnet_style_object_initializer = true:warning
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
dotnet_style_prefer_inferred_anonymous_type_member_names = true:silent
dotnet_style_prefer_inferred_tuple_names = true:silent
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
dotnet_style_prefer_simplified_boolean_expressions = true:warning
dotnet_style_prefer_simplified_interpolation = true:suggestion

# 字段首选项
dotnet_style_readonly_field = true:suggestion

# 参数首选项
dotnet_code_quality_unused_parameters = all:warning

# 禁止显示首选项
dotnet_remove_unnecessary_suppression_exclusions = none

#### c# 编码约定 ####

# var 首选项
csharp_style_var_elsewhere = true:silent
csharp_style_var_for_built_in_types = true:warning
csharp_style_var_when_type_is_apparent = true:warning

# Expression-bodied 成员
csharp_style_expression_bodied_accessors = when_on_single_line:warning
csharp_style_expression_bodied_constructors = false:suggestion
csharp_style_expression_bodied_indexers = when_on_single_line:warning
csharp_style_expression_bodied_lambdas = when_on_single_line:suggestion
csharp_style_expression_bodied_local_functions = false:suggestion
csharp_style_expression_bodied_methods = false:suggestion
csharp_style_expression_bodied_operators = false:suggestion
csharp_style_expression_bodied_properties = when_on_single_line:warning

# 模式匹配首选项
csharp_style_pattern_matching_over_as_with_null_check = true:warning
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
csharp_style_prefer_not_pattern = true:warning
csharp_style_prefer_pattern_matching = true:warning
csharp_style_prefer_switch_expression = true:warning

# Null 检查首选项
csharp_style_conditional_delegate_call = true:warning

# 修饰符首选项
csharp_prefer_static_local_function = true:suggestion
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion

# 代码块首选项
csharp_prefer_braces = true:warning
csharp_prefer_simple_using_statement = true:suggestion

# 表达式级首选项
csharp_prefer_simple_default_expression = true:warning
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_inlined_variable_declaration = true:warning
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:warning
csharp_style_prefer_range_operator = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:silent
csharp_style_unused_value_expression_statement_preference = discard_variable:silent

# "using" 指令首选项
csharp_using_directive_placement = outside_namespace:warning

#### C# 格式规则 ####

# 新行首选项
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true

# 缩进首选项
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = false
csharp_indent_labels = flush_left
csharp_indent_switch_labels = true

# 空格键首选项
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false

# 包装首选项
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false

#### 命名样式 ####

# 命名规则

dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i

dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case

dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case

# 符号规范

dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal
dotnet_naming_symbols.interface.required_modifiers = 

dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal
dotnet_naming_symbols.types.required_modifiers = 

dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal
dotnet_naming_symbols.non_field_members.required_modifiers = 

# 命名样式

dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case

dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: "[BUG]"
labels: Bug
assignees: ''

---

**描述 bug**

简要描述所遇到的bug

**如何复现**

说明您在进行了怎样的操作后出现了bug:

1. 
2. 
3. 

**预期行为**

简要描述进行以上操作后预期的脚本行为

**截图**

如果可以,请添加屏幕截图以帮助解释您的问题

**环境**

 - 系统:[如 Windows 10 1809]
 - 浏览器:[如 Chrome 74.0.3729.157,无关则删除]
 - 程序版本:[如 5.0.0.0 .Net Core SelfContained x64]
 
**其它内容**

在此添加有关此问题的任何其它内容。
最好能贴上相关的日志


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Telegram Channel
    url: https://t.me/ShadowsocksR_Windows
    about: Telegram Channel

================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: Enhancement
assignees: ''

---

**您的功能请求是否与 BUG 有关? 请描述一下。**

简明扼要地描述了问题所在

**描述您想要的解决方案**

简明扼要地描述您想要发生的事情

**描述您考虑过的替代方案**

对您考虑的任何替代解决方案或功能的简明扼要描述

**其它内容**

在此处添加有关功能请求的任何其它内容或屏幕截图


================================================
FILE: .github/ISSUE_TEMPLATE/other-issue.md
================================================
---
name: Other issue
about: Other issue
title: ''
labels: ''
assignees: ''

---

之所以写中文,本issue是写给打算写给乱发中文问题的人看的

1. 不欢迎小白,不回答诸如软件如何使用,如何搭建,如何配置,使用速度不快,如何提速等等和软件问题无关的问题,或把开发者当成客服的问题
2. 这里用于反馈软件可能的Bug,软件潜在的问题,和软件功能需求及讨论
3. 同一个issue不得在不同repo重复发,除非你发现发错地方(这种情况下你自行删除错误的issue),否则直接关闭且不回答问题,严重者拉黑名单
4. 建议你把问题事先在其它社区或和其它使用者讨论过,以确认不是密码错误,协议或插件错误,或服务器防火墙没关诸如此类本来应该自己解决的问题
5. 在你确认你需要发问题时,请尽可能提供详细的信息,包括服务端客户端具体版本,及相应log,及相应服务端客户端协议混淆等等的配置。如信息明显过少,则直接close不理踩

确认你读完以上内容后,请删除以上所有内容,然后写下你的问题

Please remove all above then write down your issue


================================================
FILE: .github/renovate.json
================================================
{
	"$schema": "https://docs.renovatebot.com/renovate-schema.json",
	"assignees": [
		"HMBSbige"
	],
	"commitMessagePrefix": "dep:",
	"dependencyDashboard": false,
	"extends": [
		"config:base",
		":automergeBranch",
		":automergeDigest",
		":automergeMinor",
		":disableRateLimiting"
	],
	"packageRules": [
		{
			"matchPackagePrefixes": [
				"Syncfusion"
			],
			"groupName": "Syncfusion"
		}
	],
	"labels": [
		"Automatic"
	]
}

================================================
FILE: .github/workflows/CI.yml
================================================
name: CI
on: [push, pull_request, workflow_dispatch]
env:
  ProjectName: ShadowsocksR

jobs:

  build:
    name: Build
    runs-on: windows-latest
    env:
      SyncfusionLicenseKey: ${{ secrets.SyncfusionLicenseKey }}
      NET_TFM: net7.0-windows
      Configuration: Release

    steps:
    - name: Checkout code
      uses: actions/checkout@v4
      with:
        submodules: true

    - name: Setup .NET
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: 7.0.x

    - name: Setup NuGet Private Sources
      shell: pwsh
      run: dotnet nuget add source https://nuget.pkg.github.com/HMBSbige/index.json -n GitHub-HMBSbige -u HMBSbige -p ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text

    - name: Build .NET App
      shell: pwsh
      run: .\build.ps1 app

    - name: Build x64
      shell: pwsh
      run: .\build.ps1 x64

    - name: Build x86
      shell: pwsh
      run: .\build.ps1 x86

    - name: Upload .NET App
      continue-on-error: true
      if: ${{ !startsWith(github.ref, 'refs/tags/') }}
      uses: actions/upload-artifact@v4
      with:
        name: ${{ env.ProjectName }}
        path: shadowsocks-csharp\bin\${{ env.Configuration }}\${{ env.NET_TFM }}\publish\

    - name: Upload x64
      continue-on-error: true
      if: ${{ !startsWith(github.ref, 'refs/tags/') }}
      uses: actions/upload-artifact@v4
      with:
        name: ${{ env.ProjectName }}-Win64
        path: shadowsocks-csharp\bin\${{ env.Configuration }}\${{ env.NET_TFM }}\win-x64\publish\

    - name: Upload x86
      continue-on-error: true
      if: ${{ !startsWith(github.ref, 'refs/tags/') }}
      uses: actions/upload-artifact@v4
      with:
        name: ${{ env.ProjectName }}-Win32
        path: shadowsocks-csharp\bin\${{ env.Configuration }}\${{ env.NET_TFM }}\win-x86\publish\

    - name: Get tag
      if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
      id: tag
      uses: dawidd6/action-get-tag@v1

    - name: Package .NET App
      if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
      shell: pwsh
      run: |
        New-Item -ItemType Directory -Path C:\builtfiles -Force > $null
        $zip_path = "C:\builtfiles\$env:ProjectName-${{ steps.tag.outputs.tag }}.7z"
        7z a -mx9 "$zip_path" ".\shadowsocks-csharp\bin\$env:Configuration\$env:NET_TFM\publish\"
        7z rn "$zip_path" publish $env:ProjectName
        echo "NET_SHA256=$((Get-FileHash $zip_path -Algorithm SHA256).Hash)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

    - name: Package x64
      if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
      shell: pwsh
      run: |
        New-Item -ItemType Directory -Path C:\builtfiles -Force > $null
        $zip_path = "C:\builtfiles\$env:ProjectName-Win64-${{ steps.tag.outputs.tag }}.7z"
        7z a -mx9 "$zip_path" ".\shadowsocks-csharp\bin\$env:Configuration\$env:NET_TFM\win-x64\publish\"
        7z rn "$zip_path" publish $env:ProjectName
        echo "NET64_SHA256=$((Get-FileHash $zip_path -Algorithm SHA256).Hash)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

    - name: Package x86
      if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
      shell: pwsh
      run: |
        New-Item -ItemType Directory -Path C:\builtfiles -Force > $null
        $zip_path = "C:\builtfiles\$env:ProjectName-Win32-${{ steps.tag.outputs.tag }}.7z"
        7z a -mx9 "$zip_path" ".\shadowsocks-csharp\bin\$env:Configuration\$env:NET_TFM\win-x86\publish\"
        7z rn "$zip_path" publish $env:ProjectName
        echo "NET86_SHA256=$((Get-FileHash $zip_path -Algorithm SHA256).Hash)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

    - name: Create a new GitHub release if a new tag is pushed
      uses: ncipollo/release-action@v1
      if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        name: v${{ steps.tag.outputs.tag }}
        prerelease: true
        draft: false
        artifacts: C:\builtfiles\*
        body: |
          [![](https://img.shields.io/badge/Channel-blue?label=Telegram&logo=telegram)](https://t.me/ShadowsocksR_Windows) [![](https://img.shields.io/badge/Group-green?label=Telegram&logo=telegram)](https://t.me/joinchat/Gn-Aa0-j4HcpdBaW-Iv8Sw)

          ## 更新日志:
          * 这是 GitHub Action 自动化部署,更新日志应该很快会手动更新

          ## 文件校验
          | 文件名 | SHA256 |
          | :- | :- |
          | <sub>${{ env.ProjectName }}-${{ steps.tag.outputs.tag }}.7z</sub> | <sub>${{ env.NET_SHA256 }}</sub> |
          | <sub>${{ env.ProjectName }}-Win64-${{ steps.tag.outputs.tag }}.7z</sub> | <sub>${{ env.NET64_SHA256 }}</sub> |
          | <sub>${{ env.ProjectName }}-Win32-${{ steps.tag.outputs.tag }}.7z</sub> | <sub>${{ env.NET86_SHA256 }}</sub> |


================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Mono auto generated files
mono_crash.*

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# Visual Studio 2017 auto generated files
Generated\ Files/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# Benchmark Results
BenchmarkDotNet.Artifacts/

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/

# StyleCop
StyleCopReport.xml

# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# Visual Studio Trace Files
*.e2e

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak

# SQL Server files
*.mdf
*.ldf
*.ndf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# CodeRush personal settings
.cr/personal

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# Tabs Studio
*.tss

# Telerik's JustMock configuration file
*.jmconfig

# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

# OpenCover UI analysis results
OpenCover/

# Azure Stream Analytics local run output
ASALocalRun/

# MSBuild Binary and Structured Log
*.binlog

# NVidia Nsight GPU debugger configuration file
*.nvuser

# MFractors (Xamarin productivity tool) working folder
.mfractor/

# Local History for Visual Studio
.localhistory/

# BeatPulse healthcheck temp database
healthchecksdb

# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/

================================================
FILE: Build/DotNetDllPathPatcher.ps1
================================================
using namespace System.IO
using namespace System.Text

param([string]$exe_path, [string]$target_path = 'bin')
$ErrorActionPreference = 'Stop'
#$DebugPreference = 'Continue'

$exe_path = (Resolve-Path -Path $exe_path).Path

Write-Host "Origin path: `"$exe_path`""
Write-Host "Target dll path: $target_path"

$separator = '\'
$max_path_length = 1024

$exe_name = [Path]::GetFileName($exe_path)
$dll_name = [Path]::ChangeExtension($exe_name, '.dll')
Write-Debug "exe: $exe_name"
Write-Debug "dll: $dll_name"

function Update-Exe {
    $old_bytes = [Encoding]::UTF8.GetBytes("$dll_name`0")
    if ($old_bytes.Count -gt $max_path_length) {
        throw [PathTooLongException] 'old dll path is too long'
    }

    $new_dll_path = "$target_path$separator$dll_name"
    $new_bytes = [Encoding]::UTF8.GetBytes("$new_dll_path`0")
    Write-Host "Dll path Change to `"$new_dll_path`""
    if ($new_bytes.Count -gt $max_path_length) {
        throw [PathTooLongException] 'new dll path is too long'
    }

    $bytes = [File]::ReadAllBytes($exe_path)
    $index = (Get-Content $exe_path -Raw -Encoding 28591).IndexOf("$dll_name`0")
    if ($index -lt 0) {
        throw [InvalidDataException] 'Could not find old dll path'
    }
    Write-Debug "Position: $index"
    $end_postion = $index + $($new_bytes.Count)
    $end_length = $bytes.Count - $end_postion
    if ($end_postion -gt $bytes.Count) {
        throw [PathTooLongException] 'new dll path is too long'
    }
    Write-Debug "End Position: $end_postion"
    Write-Debug "End Length: $end_length"

    $fs = [File]::OpenWrite($exe_path)
    try {
        $fs.Write($bytes, 0, $index)
        $fs.Write($new_bytes)
        $fs.Write($bytes, $end_postion, $end_length)
    }
    finally {
        $fs.Dispose();
    }
}

function Move-Dll {
    $tmpbin = 'tmpbin'
    $dir = [Path]::GetDirectoryName($exe_path);
    $root = [Path]::GetDirectoryName($dir);
    Write-Debug "root path: $root"
    Write-Debug "dir path: $dir"

    Rename-Item $dir $tmpbin
    New-Item -ItemType Directory $dir > $null
    Move-Item $root\$tmpbin $dir
    Rename-Item $dir\$tmpbin $target_path
    Move-Item $dir\$target_path\$exe_name $dir
}

Update-Exe
Move-Dll

================================================
FILE: CONTRIBUTING.md
================================================
How to Contribute
=================

Pull Requests
-------------

1. Pull requests are welcome.
2. Make sure to pass the unit tests. Write unit tests for new modules if
needed.


================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    {one line to give the program's name and a brief idea of what it does.}
    Copyright (C) {year}  {name of author}

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    {project}  Copyright (C) {year}  {fullname}
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.



================================================
FILE: README.md
================================================
<img src="shadowsocks-csharp/Resources/ssw128.png" width="48"/>ShadowsocksR for Windows
=======================

[![](https://img.shields.io/badge/Channel-blue?label=Telegram&logo=telegram)](https://t.me/ShadowsocksR_Windows)
[![](https://img.shields.io/badge/Group-green?label=Telegram&logo=telegram)](https://t.me/joinchat/Gn-Aa0-j4HcpdBaW-Iv8Sw)

## Build

[![](https://github.com/HMBSbige/ShadowsocksR-Windows/workflows/CI/badge.svg)](https://github.com/HMBSbige/ShadowsocksR-Windows/actions)

## [Wiki](https://github.com/HMBSbige/ShadowsocksR-Windows/wiki)

## Download

* [latest release]

## Develop

Visual Studio Community 2022 is recommended.

## License

GPLv3

Copyright © 2019 - 2022 HMBSbige. Forked from ShadowsocksR by BreakWa11

[latest release]: https://github.com/HMBSbige/ShadowsocksR-Windows/releases


================================================
FILE: UnitTest/DnsTest.cs
================================================
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shadowsocks.Enums;
using Shadowsocks.Util.NetUtils;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace UnitTest;

[TestClass]
public class DnsTest
{
    [TestMethod]
    public async Task DefaultTest()
    {
        var ip1 = await DnsUtil.QueryDefaultAsync(@"dns.google");
        Assert.IsTrue(Equals(ip1, IPAddress.Parse(@"8.8.8.8")) || Equals(ip1, IPAddress.Parse(@"8.8.4.4")));
        var ip2 = await DnsUtil.QueryDefaultAsync(@"dns.google", true);
        Assert.IsTrue(Equals(ip2, IPAddress.Parse(@"2001:4860:4860::8888")) || Equals(ip2, IPAddress.Parse(@"2001:4860:4860::8844")));
    }

    [TestMethod]
    public async Task Test()
    {
        var client = new Shadowsocks.Model.DnsClient(DnsType.Default)
        {
            DnsServer = @"101.6.6.6",
            Port = 5353,
            IsTcpEnabled = true,
            IsUdpEnabled = false
        };
        var ip = await client.QueryIpAddressAsync(@"www.google.com", default);
        Assert.IsNotNull(ip);
        Console.WriteLine(ip);
    }

    [TestMethod]
    public async Task DnsOverTlsTest()
    {
        var client = new Shadowsocks.Model.DnsClient(DnsType.DnsOverTls);
        var ip = await client.QueryIpAddressAsync(@"www.google.com", default);
        Assert.IsNotNull(ip);
        Console.WriteLine(ip);
    }

    [TestMethod]
    public async Task TestTwoDnsAsync()
    {
        const string host = @"www.google.com";
        var clients = new List<Shadowsocks.Model.DnsClient>
        {
            new(DnsType.Default)
            {
                DnsServer = @"101.6.6.6",
                Port = 5353,
                IsTcpEnabled = true,
                IsUdpEnabled = false
            },
            new(DnsType.DnsOverTls)
        };
        var res = await DnsUtil.QueryAsync(host, clients);
        Assert.IsNotNull(res);
        Console.WriteLine(res);
    }

    [TestMethod]
    public async Task TestIpv6FallbackAsync()
    {
        const string host = @"speed.neu6.edu.cn";

        var resDefault = await DnsUtil.QueryDefaultAsync(host);
        Assert.IsNotNull(resDefault);
        Console.WriteLine(resDefault);

        var clients = new List<Shadowsocks.Model.DnsClient>
        {
            new(DnsType.DnsOverTls)
            {
                DnsServer = @"dns.alidns.com"
            },
            new(DnsType.Default)
            {
                DnsServer = @"114.114.114.114",
                Port = 53,
                IsTcpEnabled = true,
                IsUdpEnabled = false
            }
        };
        var res = await DnsUtil.QueryAsync(host, clients);
        Assert.IsNotNull(res);
        Console.WriteLine(res);
    }

    [TestMethod]
    public async Task TestIpv6FirstAsync()
    {
        const string host = @"speed.neu.edu.cn";
        var clients = new List<Shadowsocks.Model.DnsClient>
        {
            new(DnsType.Default)
            {
                DnsServer = @"114.114.114.114",
                Port = 53,
                IsTcpEnabled = true,
                IsUdpEnabled = false,
                Ipv6First = true
            }
        };
        var res = await DnsUtil.QueryAsync(host, clients);

        Assert.IsNotNull(res);
        Assert.AreEqual(AddressFamily.InterNetworkV6, res.AddressFamily);
        Console.WriteLine(res);
    }
}


================================================
FILE: UnitTest/EncryptionTest.cs
================================================
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shadowsocks.Encryption;
using Shadowsocks.Encryption.Stream;
using Shadowsocks.Util;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace UnitTest
{
    [TestClass]
    public class EncryptionTest
    {
        private void RunEncryptionRound(IEncryptor encryptor, IEncryptor decryptor)
        {
            var plain = new byte[16384];
            var cipher = new byte[plain.Length + 16];
            var plain2 = new byte[plain.Length + 16];
            Rng.RandBytes(plain);
            encryptor.Encrypt(plain, plain.Length, cipher, out var outLen);
            decryptor.Decrypt(cipher, outLen, plain2, out var outLen2);
            Assert.AreEqual(plain.Length, outLen2);
            for (var j = 0; j < plain.Length; j++)
            {
                Assert.AreEqual(plain[j], plain2[j]);
            }
            encryptor.Encrypt(plain, 1000, cipher, out outLen);
            decryptor.Decrypt(cipher, outLen, plain2, out outLen2);
            Assert.AreEqual(1000, outLen2);
            for (var j = 0; j < outLen2; j++)
            {
                Assert.AreEqual(plain[j], plain2[j]);
            }
            encryptor.Encrypt(plain, 12333, cipher, out outLen);
            decryptor.Decrypt(cipher, outLen, plain2, out outLen2);
            Assert.AreEqual(12333, outLen2);
            for (var j = 0; j < outLen2; j++)
            {
                Assert.AreEqual(plain[j], plain2[j]);
            }
        }

        [TestMethod]
        public void TestStreamOpenSSLEncryption()
        {
            var failed = false;
            // run it once before the multi-threading test to initialize global tables
            RunSingleStreamOpenSSLEncryptionThread();

            var tasks = new List<Task>();
            foreach (var cipher in StreamOpenSSLEncryptor.SupportedCiphers())
            {
                if (cipher.EndsWith(@"-cbc"))
                {
                    continue;
                }
                var t = new Task(() =>
                {
                    try
                    {
                        RunSingleStreamOpenSSLEncryptionThread(cipher);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($@"{cipher}:{e.Message}");
                        failed = true;
                        throw;
                    }
                });
                tasks.Add(t);
                t.Start();
            }

            Task.WaitAll(tasks.ToArray());
            Assert.IsFalse(failed);
        }

        private void RunSingleStreamOpenSSLEncryptionThread(string methodName = @"aes-256-cfb8", string password = @"barfoo!")
        {
            for (var i = 0; i < 100; i++)
            {
                IEncryptor encryptor = new StreamOpenSSLEncryptor(methodName, password);
                IEncryptor decryptor = new StreamOpenSSLEncryptor(methodName, password);
                RunEncryptionRound(encryptor, decryptor);
            }
        }

        [TestMethod]
        public void TestStreamSodiumEncryption()
        {
            var failed = false;
            // run it once before the multi-threading test to initialize global tables
            RunSingleStreamSodiumEncryptionThread();
            var tasks = new List<Task>();
            foreach (var cipher in StreamSodiumEncryptor.SupportedCiphers())
            {
                if (cipher.StartsWith(@"x"))
                {
                    continue;
                }
                var t = new Task(() =>
                {
                    try
                    {
                        RunSingleStreamSodiumEncryptionThread(cipher);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($@"{cipher}:{e.Message}");
                        failed = true;
                        throw;
                    }
                });
                tasks.Add(t);
                t.Start();
            }

            Task.WaitAll(tasks.ToArray());
            Assert.IsFalse(failed);
        }

        private void RunSingleStreamSodiumEncryptionThread(string methodName = @"salsa20", string password = @"barfoo!")
        {
            for (var i = 0; i < 100; i++)
            {
                IEncryptor encryptor = new StreamSodiumEncryptor(methodName, password);
                IEncryptor decryptor = new StreamSodiumEncryptor(methodName, password);
                RunEncryptionRound(encryptor, decryptor);
            }
        }
    }
}


================================================
FILE: UnitTest/IPSubnet.cs
================================================
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shadowsocks.Util.NetUtils;
using System.Net;

namespace UnitTest
{
    [TestClass]
    public class IPSubnetTest
    {
        [TestMethod]
        public void IsLoopBackTest()
        {
            Assert.IsTrue(IPSubnet.IsLoopBack(IPAddress.Loopback));
            Assert.IsTrue(IPSubnet.IsLoopBack(IPAddress.IPv6Loopback));
            Assert.IsTrue(IPSubnet.IsLoopBack(IPAddress.Parse(@"127.0.0.255")));
            Assert.IsTrue(IPSubnet.IsLoopBack(IPAddress.Parse(@"127.255.255.255")));
            Assert.IsFalse(IPSubnet.IsLoopBack(IPAddress.Parse(@"192.168.1.1")));
            Assert.IsFalse(IPSubnet.IsLoopBack(IPAddress.Parse(@"2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFFF")));
        }

        [TestMethod]
        public void IsInSubnetTest()
        {
            Assert.IsTrue(IPAddress.Parse(@"192.168.5.1").IsInSubnet(@"192.168.5.85/24"));
            Assert.IsTrue(IPAddress.Parse(@"192.168.5.254").IsInSubnet(@"192.168.5.85/24"));
            Assert.IsTrue(IPAddress.Parse(@"10.128.240.48").IsInSubnet(@"10.128.240.50/30"));
            Assert.IsTrue(IPAddress.Parse(@"10.128.240.49").IsInSubnet(@"10.128.240.50/30"));
            Assert.IsTrue(IPAddress.Parse(@"10.128.240.50").IsInSubnet(@"10.128.240.50/30"));
            Assert.IsTrue(IPAddress.Parse(@"10.128.240.51").IsInSubnet(@"10.128.240.50/30"));

            Assert.IsFalse(IPAddress.Parse(@"192.168.4.254").IsInSubnet(@"192.168.5.85/24"));
            Assert.IsFalse(IPAddress.Parse(@"191.168.5.254").IsInSubnet(@"192.168.5.85/24"));
            Assert.IsFalse(IPAddress.Parse(@"10.128.240.47").IsInSubnet(@"10.128.240.50/30"));
            Assert.IsFalse(IPAddress.Parse(@"10.128.240.52").IsInSubnet(@"10.128.240.50/30"));
            Assert.IsFalse(IPAddress.Parse(@"10.128.239.50").IsInSubnet(@"10.128.240.50/30"));
            Assert.IsFalse(IPAddress.Parse(@"10.127.240.51").IsInSubnet(@"10.128.240.50/30"));

            Assert.IsTrue(IPAddress.Parse(@"2001:0DB8:ABCD:0012:0000:0000:0000:0000").IsInSubnet(@"2001:db8:abcd:0012::0/64"));
            Assert.IsTrue(IPAddress.Parse(@"2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFFF").IsInSubnet(@"2001:db8:abcd:0012::0/64"));
            Assert.IsTrue(IPAddress.Parse(@"2001:0DB8:ABCD:0012:0001:0000:0000:0000").IsInSubnet(@"2001:db8:abcd:0012::0/64"));
            Assert.IsTrue(IPAddress.Parse(@"2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFF0").IsInSubnet(@"2001:db8:abcd:0012::0/64"));
            Assert.IsTrue(IPAddress.Parse(@"2001:0DB8:ABCD:0012:0000:0000:0000:0000").IsInSubnet(@"2001:db8:abcd:0012::0/128"));

            Assert.IsFalse(IPAddress.Parse(@"2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFFF").IsInSubnet(@"2001:db8:abcd:0012::0/64"));
            Assert.IsFalse(IPAddress.Parse(@"2001:0DB8:ABCD:0013:0000:0000:0000:0000").IsInSubnet(@"2001:db8:abcd:0012::0/64"));
            Assert.IsFalse(IPAddress.Parse(@"2001:0DB8:ABCD:0013:0001:0000:0000:0000").IsInSubnet(@"2001:db8:abcd:0012::0/64"));
            Assert.IsFalse(IPAddress.Parse(@"2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFF0").IsInSubnet(@"2001:db8:abcd:0012::0/64"));
            Assert.IsFalse(IPAddress.Parse(@"2001:0DB8:ABCD:0012:0000:0000:0000:0001").IsInSubnet(@"2001:db8:abcd:0012::0/128"));
        }
    }
}


================================================
FILE: UnitTest/ServerTest.cs
================================================
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shadowsocks.Model;
using System;

namespace UnitTest
{
    [TestClass]
    public class ServerTest
    {
        [TestMethod]
        public void TestServerFromSSR()
        {
            var server = new Server();
            var nornameCase = "ssr://MTI3LjAuMC4xOjEyMzQ6YXV0aF9hZXMxMjhfbWQ1OmFlcy0xMjgtY2ZiOnRsczEuMl90aWNrZXRfYXV0aDpZV0ZoWW1KaS8_b2Jmc3BhcmFtPVluSmxZV3QzWVRFeExtMXZaUQ";

            server.ServerFromSsr(nornameCase, "");

            Assert.AreEqual(server.server, "127.0.0.1");
            Assert.AreEqual(server.Server_Port, (ushort)1234);
            Assert.AreEqual(server.Protocol, "auth_aes128_md5");
            Assert.AreEqual(server.Method, "aes-128-cfb");
            Assert.AreEqual(server.obfs, "tls1.2_ticket_auth");
            Assert.AreEqual(server.ObfsParam, "breakwa11.moe");
            Assert.AreEqual(server.Password, "aaabbb");

            server = new Server();
            const string normalCaseWithRemark = "ssr://MTI3LjAuMC4xOjEyMzQ6YXV0aF9hZXMxMjhfbWQ1OmFlcy0xMjgtY2ZiOnRsczEuMl90aWNrZXRfYXV0aDpZV0ZoWW1KaS8_b2Jmc3BhcmFtPVluSmxZV3QzWVRFeExtMXZaUSZyZW1hcmtzPTVyV0w2Sy1WNUxpdDVwYUg";

            server.ServerFromSsr(normalCaseWithRemark, "firewallAirport");

            Assert.AreEqual(server.server, "127.0.0.1");
            Assert.AreEqual<ushort>(server.Server_Port, 1234);
            Assert.AreEqual(server.Protocol, "auth_aes128_md5");
            Assert.AreEqual(server.Method, "aes-128-cfb");
            Assert.AreEqual(server.obfs, "tls1.2_ticket_auth");
            Assert.AreEqual(server.ObfsParam, "breakwa11.moe");
            Assert.AreEqual(server.Password, "aaabbb");

            Assert.AreEqual(server.Remarks, "测试中文");
            Assert.AreEqual(server.Group, string.Empty);
            Assert.AreEqual(server.SubTag, "firewallAirport");
        }

        [TestMethod]
        public void TestBadPortNumber()
        {
            var server = new Server();

            const string link = "ssr://MTI3LjAuMC4xOjgwOmF1dGhfc2hhMV92NDpjaGFjaGEyMDpodHRwX3NpbXBsZTplaWZnYmVpd3ViZ3IvP29iZnNwYXJhbT0mcHJvdG9wYXJhbT0mcmVtYXJrcz0mZ3JvdXA9JnVkcHBvcnQ9NDY0MzgxMzYmdW90PTQ2MDA3MTI4";
            try
            {
                server.ServerFromSsr(link, "");
            }
            catch (OverflowException e)
            {
                Console.Write(e.ToString());
            }

        }
    }
}


================================================
FILE: UnitTest/SubscribeTest.cs
================================================
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shadowsocks.Controller.HttpRequest;
using Shadowsocks.Util;
using System;
using System.Text.RegularExpressions;

namespace UnitTest
{
    [TestClass]
    public class SubscribeTest
    {
        [TestMethod]
        public void ParseTest()
        {
            var url = @"sub://aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0hNQlNiaWdlL1RleHRfVHJhbnNsYXRpb24vbWFzdGVyL1NoYWRvd3NvY2tzUi9mcmVlbm9kZXBsYWluLnR4dA";
            var sub = Regex.Match(url, "sub://([A-Za-z0-9_-]+)", RegexOptions.IgnoreCase);
            if (!sub.Success)
            {
                throw new FormatException();
            }

            var res = Base64.DecodeUrlSafeBase64(sub.Groups[1].Value);
            Assert.AreEqual(res, UpdateNode.DefaultUpdateUrl);
        }
    }
}


================================================
FILE: UnitTest/UnitTest.cs
================================================
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shadowsocks.Encryption;
using Shadowsocks.Util;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace UnitTest
{
    [TestClass]
    public class UnitTest
    {
        [TestMethod]
        public void TestMd5()
        {
            var buff = Encoding.UTF8.GetBytes(@"密码");
            var md5Sum = CryptoUtils.MD5(buff);
            var md5Hash = MD5.Create().ComputeHash(buff);
            Assert.IsTrue(md5Hash.SequenceEqual(md5Sum));
        }

        [TestMethod]
        public void EncryptStringTest()
        {
            var largeBytes = new byte[ushort.MaxValue * 100];
            Rng.RandBytes(largeBytes);
            var largeStr = Encoding.UTF8.GetString(largeBytes);
            using var encryptor = EncryptorFactory.GetEncryptor(@"aes-256-cfb", @"密码");

            var encodeStr = Utils.EncryptLargeBytesToBase64String(encryptor, largeBytes);

            var decodeStr = Encoding.UTF8.GetString(Utils.DecryptLargeBase64StringToBytes(encryptor, encodeStr));

            Assert.AreEqual(largeStr, decodeStr);
        }

    }
}


================================================
FILE: UnitTest/UnitTest.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net7.0-windows</TargetFramework>
    <LangVersion>latest</LangVersion>
    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
    <PackageReference Include="MSTest.TestAdapter" Version="3.9.3" />
    <PackageReference Include="MSTest.TestFramework" Version="3.9.3" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\shadowsocks-csharp\shadowsocksr.csproj" />
  </ItemGroup>

</Project>


================================================
FILE: build.ps1
================================================
param([string]$buildtfm = 'all')
$ErrorActionPreference = 'Stop'

Write-Host 'dotnet SDK info'
dotnet --info

$exe = 'ShadowsocksR.exe'
$net_tfm = 'net7.0-windows'
$configuration = 'Release'
$output_dir = "$PSScriptRoot\shadowsocks-csharp\bin\$configuration"
$proj_path = "$PSScriptRoot\shadowsocks-csharp\shadowsocksr.csproj"

$build    = $buildtfm -eq 'all' -or $buildtfm -eq 'app'
$buildX86 = $buildtfm -eq 'all' -or $buildtfm -eq 'x86'
$buildX64 = $buildtfm -eq 'all' -or $buildtfm -eq 'x64'
function Build-App
{
	Write-Host 'Building .NET App'
	
	$outdir = "$output_dir\$net_tfm"
	$publishDir = "$outdir\publish"

	Remove-Item $publishDir -Recurse -Force -Confirm:$false -ErrorAction Ignore
	
	dotnet publish -c $configuration -f $net_tfm $proj_path
	if ($LASTEXITCODE) { exit $LASTEXITCODE }

	& "$PSScriptRoot\Build\DotNetDllPathPatcher.ps1" $publishDir\$exe bin
	if ($LASTEXITCODE) { exit $LASTEXITCODE }
}

function Build-SelfContained
{
	param([string]$rid)

	Write-Host "Building .NET App SelfContained $rid"

	$outdir = "$output_dir\$net_tfm\$rid"
	$publishDir = "$outdir\publish"

	Remove-Item $publishDir -Recurse -Force -Confirm:$false -ErrorAction Ignore

	dotnet publish -c $configuration -f $net_tfm -r $rid --self-contained true $proj_path
	if ($LASTEXITCODE) { exit $LASTEXITCODE }

	& "$PSScriptRoot\Build\DotNetDllPathPatcher.ps1" $publishDir\$exe bin
	if ($LASTEXITCODE) { exit $LASTEXITCODE }
}

if ($build)
{
	Build-App
}

if ($buildX64)
{
	Build-SelfContained win-x64
}

if ($buildX86)
{
	Build-SelfContained win-x86
}

================================================
FILE: shadowsocks-csharp/Controller/AutoStartup.cs
================================================
using CryptoBase;
using RunAtStartup;
using System;
using System.IO;
using Utils = Shadowsocks.Util.Utils;

namespace Shadowsocks.Controller
{
    internal static class AutoStartup
    {
        private static readonly string Key = $@"ShadowsocksR_{Directory.GetCurrentDirectory().GetClassicHashCode()}";

        public static bool Set(bool enabled)
        {
            try
            {
                var path = $@"""{Utils.GetExecutablePath()}""";
                var service = new StartupService(Key);
                if (enabled)
                {
                    service.Set(path);
                }
                else
                {
                    service.Delete();
                }
                return true;
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
                return false;
            }
        }

        public static bool Check()
        {
            try
            {
                var path = $@"""{Utils.GetExecutablePath()}""";
                var service = new StartupService(Key);
                return service.Check(path);
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
                return false;
            }
        }
    }
}


================================================
FILE: shadowsocks-csharp/Controller/FileManager.cs
================================================
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Threading.Tasks;

namespace Shadowsocks.Controller
{
    public static class FileManager
    {
        public static bool ByteArrayToFile(string fileName, byte[] content)
        {
            try
            {
                var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
                fileStream.Write(content, 0, content.Length);
                fileStream.Close();
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($@"Exception caught in process: {ex}");
            }
            return false;
        }

        public static void DecompressFile(string fileName, byte[] content)
        {
            var destinationFile = File.Create(fileName);

            // Because the uncompressed size of the file is unknown, 
            // we are using an arbitrary buffer size.
            var buffer = new byte[4096];

            using (var input = new GZipStream(new MemoryStream(content), CompressionMode.Decompress, false))
            {
                while (true)
                {
                    var n = input.Read(buffer, 0, buffer.Length);
                    if (n == 0)
                    {
                        break;
                    }
                    destinationFile.Write(buffer, 0, n);
                }
            }
            destinationFile.Close();
        }

        public static byte[] DeflateCompress(byte[] content, int index, int count, out int size)
        {
            size = 0;
            try
            {
                var memStream = new MemoryStream();
                using (var ds = new DeflateStream(memStream, CompressionMode.Compress))
                {
                    ds.Write(content, index, count);
                }
                var buffer = memStream.ToArray();
                size = buffer.Length;
                return buffer;
            }
            catch (Exception ex)
            {
                Console.WriteLine($@"Exception caught in process: {ex}");
            }
            return null;
        }

        public static byte[] DeflateDecompress(byte[] content, int index, int count, out int size)
        {
            size = 0;
            try
            {
                var buffer = new byte[16384];
                var ds = new DeflateStream(new MemoryStream(content, index, count), CompressionMode.Decompress);
                while (true)
                {
                    var readSize = ds.Read(buffer, size, buffer.Length - size);
                    if (readSize == 0)
                    {
                        break;
                    }
                    size += readSize;
                    var newBuffer = new byte[buffer.Length * 2];
                    buffer.CopyTo(newBuffer, 0);
                    buffer = newBuffer;
                }
                return buffer;
            }
            catch (Exception ex)
            {
                Console.WriteLine($@"Exception caught in process: {ex}");
            }
            return null;
        }

        [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
        public static async Task<bool> ZipCompressToFile(string path)
        {
            try
            {
                var filename = Path.GetFileName(path);
                var zipFilePath = $@"{Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path))}.zip";
                using (var zipFileToOpen = new FileStream(zipFilePath, FileMode.Create))
                {
                    using var archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Create);
                    var readMeEntry = archive.CreateEntry(filename);
                    using var zipStream = readMeEntry.Open();
                    using var stream = File.Open(path, FileMode.Open);
                    var bytes = new byte[(int)stream.Length];
                    var totalBytesRead = 0;
                    while (totalBytesRead < bytes.Length)
                    {
                        totalBytesRead += await stream.ReadAsync(bytes, totalBytesRead, bytes.Length - totalBytesRead);
                    }

                    await zipStream.WriteAsync(bytes, 0, bytes.Length);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public static string NonExclusiveReadAllText(string path)
        {
            return NonExclusiveReadAllText(path, Encoding.UTF8);
        }

        public static string NonExclusiveReadAllText(string path, Encoding encoding)
        {
            try
            {
                using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using var sr = new StreamReader(fs, encoding);
                return sr.ReadToEnd();
            }
            catch (Exception ex)
            {
                Logging.Error(ex);
                throw;
            }
        }
    }
}


================================================
FILE: shadowsocks-csharp/Controller/HttpRequest/GfwListUpdater.cs
================================================
using Shadowsocks.Controller.Service;
using Shadowsocks.Enums;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Shadowsocks.Controller.HttpRequest
{
    public class GfwListUpdater : HttpRequest
    {
        private const string GfwlistUrl = @"https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt";

        #region event

        public event EventHandler<ResultEventArgs> UpdateCompleted;

        public event ErrorEventHandler Error;

        public class ResultEventArgs : EventArgs
        {
            public readonly bool Success;
            public readonly PacType PacType;

            public ResultEventArgs(bool success, PacType pacType)
            {
                Success = success;
                PacType = pacType;
            }
        }

        #endregion

        #region GfwList

        public async void UpdatePacFromGfwList(Configuration config)
        {
            Logging.Info($@"Checking GFWList from {GfwlistUrl}");
            try
            {
                var userAgent = config.ProxyUserAgent;
                var proxy = CreateProxy(config);

                var content = await AutoGetAsync(GfwlistUrl, proxy, userAgent, config.ConnectTimeout * 1000, TimeSpan.FromMinutes(1).TotalMilliseconds);
                File.WriteAllText(Utils.GetTempPath(PACServer.gfwlist_FILE), content, Encoding.UTF8);
                var pacFileChanged = MergeAndWritePacFile(content);
                UpdateCompleted?.Invoke(this, new ResultEventArgs(pacFileChanged, PacType.GfwList));
            }
            catch (Exception ex)
            {
                Error?.Invoke(this, new ErrorEventArgs(ex));
            }
        }

        public static bool MergeAndWritePacFile(string gfwListResult)
        {
            var abpContent = MergePacFile(gfwListResult);
            if (File.Exists(PACDaemon.PAC_FILE))
            {
                var original = FileManager.NonExclusiveReadAllText(PACDaemon.PAC_FILE, Encoding.UTF8);
                if (original == abpContent)
                {
                    return false;
                }
            }

            File.WriteAllText(PACDaemon.PAC_FILE, abpContent, Encoding.UTF8);
            return true;
        }

        private static string MergePacFile(string gfwListResult)
        {
            var abpContent = File.Exists(PACDaemon.USER_ABP_FILE) ? FileManager.NonExclusiveReadAllText(PACDaemon.USER_ABP_FILE) : Resources.abp;

            var userRuleLines = new List<string>();
            if (File.Exists(PACDaemon.USER_RULE_FILE))
            {
                var userRulesString = FileManager.NonExclusiveReadAllText(PACDaemon.USER_RULE_FILE);
                userRuleLines = ParseToValidList(userRulesString);
            }

            var gfwLines = ParseBase64ToValidList(gfwListResult);

            abpContent = abpContent.Replace(@"__USERRULES__", JsonUtils.Serialize(userRuleLines, false))
                    .Replace(@"__RULES__", JsonUtils.Serialize(gfwLines, false));
            return abpContent;
        }

        private static List<string> ParseBase64ToValidList(string response)
        {
            var bytes = Convert.FromBase64String(response);
            var content = Encoding.ASCII.GetString(bytes);
            return ParseToValidList(content);
        }

        private static List<string> ParseToValidList(string content)
        {
            var lines = content.GetLines().ToArray();
            var validLines = new List<string>(lines.Length);
            validLines.AddRange(lines.Where(line => !line.StartsWith(@"!") && !line.StartsWith(@"[")));
            return validLines;
        }

        #endregion

        #region OnlinePAC

        public async void UpdateOnlinePac(Configuration config, string url)
        {
            try
            {
                var userAgent = config.ProxyUserAgent;
                var proxy = CreateProxy(config);

                var content = await AutoGetAsync(url, proxy, userAgent, config.ConnectTimeout * 1000, TimeSpan.FromMinutes(1).TotalMilliseconds);
                if (File.Exists(PACDaemon.PAC_FILE))
                {
                    var original = FileManager.NonExclusiveReadAllText(PACDaemon.PAC_FILE);
                    if (original == content)
                    {
                        UpdateCompleted?.Invoke(this, new ResultEventArgs(false, PacType.Online));
                        return;
                    }
                }

                File.WriteAllText(PACDaemon.PAC_FILE, content);
                UpdateCompleted?.Invoke(this, new ResultEventArgs(true, PacType.Online));
            }
            catch (Exception ex)
            {
                Error?.Invoke(this, new ErrorEventArgs(ex));
            }
        }

        #endregion

    }
}


================================================
FILE: shadowsocks-csharp/Controller/HttpRequest/HttpRequest.cs
================================================
using Shadowsocks.Model;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace Shadowsocks.Controller.HttpRequest
{
    public abstract class HttpRequest
    {
        private const string DefaultUserAgent = @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36";
        private const int DefaultGetTimeout = 30000;
        private const int DefaultHeadTimeout = 4000;

        public static HttpClient CreateClient(bool useProxy, IWebProxy proxy, string userAgent, double timeout)
        {
            var httpClientHandler = new SocketsHttpHandler
            {
                Proxy = proxy,
                UseProxy = useProxy
            };

            var client = new HttpClient(httpClientHandler)
            {
                Timeout = TimeSpan.FromMilliseconds(timeout),
                DefaultRequestVersion = HttpVersion.Version20
            };

            client.DefaultRequestHeaders.Add(@"User-Agent", string.IsNullOrWhiteSpace(userAgent) ? DefaultUserAgent : userAgent);
            return client;
        }

        private static async Task<string> GetAsync(string url, IWebProxy proxy, string userAgent = DefaultUserAgent, double timeout = DefaultGetTimeout, bool useProxy = true)
        {
            using var client = CreateClient(useProxy, proxy, userAgent, timeout);
            using var response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }

        private static async Task<bool> HeadAsync(string url, IWebProxy proxy, double timeout = DefaultHeadTimeout)
        {
            using var client = CreateClient(proxy != null, proxy, DefaultUserAgent, timeout);
            try
            {
                using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
                return true;
            }
            catch
            {
                return false;
            }
        }

        protected static async Task<string> AutoGetAsync(string url, IWebProxy proxy, string userAgent = @"", double headTimeout = DefaultHeadTimeout, double getTimeout = DefaultGetTimeout)
        {
            string res = null;
            if (await HeadAsync(url, proxy, headTimeout))
            {
                try
                {
                    res = await ProxyGetAsync(url, proxy, userAgent, getTimeout);
                }
                catch
                {
                    res = null;
                }
            }
            if (res != null)
            {
                return res;
            }

            res = await DirectGetAsync(url, userAgent, getTimeout);
            return res;
        }

        protected static async Task<string> DirectGetAsync(string url, string userAgent = DefaultUserAgent, double getTimeout = DefaultGetTimeout)
        {
            Logging.Info($@"GET request directly: {url}");
            return await GetAsync(url, null, userAgent, getTimeout, false);
        }

        protected static async Task<string> ProxyGetAsync(string url, IWebProxy proxy, string userAgent = DefaultUserAgent, double timeout = DefaultGetTimeout)
        {
            Logging.Info($@"GET request by proxy: {url}");
            return await GetAsync(url, proxy, userAgent, timeout);
        }

        protected static async Task<string> DefaultGetAsync(string url, string userAgent = DefaultUserAgent, double getTimeout = DefaultGetTimeout)
        {
            Logging.Info($@"GET request by default: {url}");
            return await GetAsync(url, null, userAgent, getTimeout);
        }

        protected static IWebProxy CreateProxy(Configuration config)
        {
            var proxy = new WebProxy(Global.LocalHost, config.LocalPort);
            if (!string.IsNullOrEmpty(config.AuthPass))
            {
                proxy.Credentials = new NetworkCredential(config.AuthUser, config.AuthPass);
            }

            return proxy;
        }
    }
}


================================================
FILE: shadowsocks-csharp/Controller/HttpRequest/UpdateChecker.cs
================================================
using Shadowsocks.Model;
using System;
using UpdateChecker;

namespace Shadowsocks.Controller.HttpRequest
{
    public class UpdateChecker : HttpRequest
    {
        private const string Owner = @"HMBSbige";
        private const string Repo = @"ShadowsocksR-Windows";

        public string LatestVersionNumber;
        public string LatestVersionUrl;

        public bool Found;

        public event EventHandler NewVersionFound;
        public event EventHandler NewVersionFoundFailed;
        public event EventHandler NewVersionNotFound;

        public const string Name = @"ShadowsocksR";
        public const string Copyright = @"Copyright © 2019 - 2022 HMBSbige. Forked from ShadowsocksR by BreakWa11";
        public const string Version = @"6.1.0";

        public const string FullVersion = Version +
#if SelfContained
#if Is64Bit
            @" x64" +
#else
            @" x86" +
#endif
#endif
#if DEBUG
        @" Debug";
#else
        @"";
#endif

        public async void Check(Configuration config, bool notifyNoFound)
        {
            try
            {
                var updater = new GitHubReleasesUpdateChecker(
                    Owner,
                    Repo,
                    config.IsPreRelease,
                    Version);

                var userAgent = config.ProxyUserAgent;
                var proxy = CreateProxy(config);
                using var client = CreateClient(true, proxy, userAgent, config.ConnectTimeout * 1000);

                var res = await updater.CheckAsync(client, default);
                LatestVersionNumber = updater.LatestVersion;
                Found = res;
                if (Found)
                {
                    LatestVersionUrl = updater.LatestVersionUrl;
                    NewVersionFound?.Invoke(this, EventArgs.Empty);
                }
                else
                {
                    if (notifyNoFound)
                    {
                        NewVersionNotFound?.Invoke(this, EventArgs.Empty);
                    }
                }
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
                if (notifyNoFound)
                {
                    NewVersionFoundFailed?.Invoke(this, EventArgs.Empty);
                }
            }
        }
    }
}


================================================
FILE: shadowsocks-csharp/Controller/HttpRequest/UpdateNode.cs
================================================
using Shadowsocks.Enums;
using Shadowsocks.Model;
using System;
using System.Net;

namespace Shadowsocks.Controller.HttpRequest
{
    public class UpdateNode : HttpRequest
    {
        public const string DefaultUpdateUrl = @"https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/freenodeplain.txt";

        public event EventHandler NewFreeNodeFound;
        public string FreeNodeResult;
        public ServerSubscribe SubscribeTask;
        public bool Notify;

        public void CheckUpdate(Configuration config, ServerSubscribe subscribeTask, bool notify)
        {
            FreeNodeResult = null;
            Notify = notify;
            try
            {
                var proxy = CreateProxy(config);
                SubscribeTask = subscribeTask;
                var url = subscribeTask.Url ?? DefaultUpdateUrl;
                Update(subscribeTask.ProxyType, proxy, config.ConnectTimeout * 1000, url, config.ProxyUserAgent);
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
            }
        }

        private async void Update(HttpRequestProxyType proxyType, IWebProxy proxy, int timeout, string url, string userAgent)
        {
            try
            {
                FreeNodeResult = proxyType switch
                {
                    HttpRequestProxyType.Auto => await AutoGetAsync(url, proxy, userAgent, timeout),
                    HttpRequestProxyType.Direct => await DirectGetAsync(url, userAgent, timeout),
                    HttpRequestProxyType.Proxy => await ProxyGetAsync(url, proxy, userAgent, timeout),
                    HttpRequestProxyType.SystemSetting => await DefaultGetAsync(url, userAgent, timeout),
                    _ => await AutoGetAsync(url, proxy, userAgent, timeout)
                };
            }
            catch (Exception ex)
            {
                Logging.Debug(ex.ToString());
            }

            NewFreeNodeFound?.Invoke(this, EventArgs.Empty);
        }
    }
}


================================================
FILE: shadowsocks-csharp/Controller/Logging.cs
================================================
using Shadowsocks.Enums;
using Shadowsocks.Obfs;
using Shadowsocks.Util;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace Shadowsocks.Controller
{
    public static class Logging
    {
        public static string LogFile;
        public static string LogFileName;
        private static string _date;

        private static FileStream _logFileStream;
        private static StreamWriterWithTimestamp _logStreamWriter;
        private static readonly object Lock = new();
        public static bool SaveToFile = true;
        public static TextWriter DefaultOut;
        public static TextWriter DefaultError;

        public static bool OpenLogFile()
        {
            try
            {
                CloseLogFile();

                if (SaveToFile)
                {
                    var newDate = DateTime.Now.ToString("yyyy-MM");
                    LogFileName = $@"shadowsocks_{newDate}.log";
                    LogFile = Utils.GetTempPath(LogFileName);
                    _logFileStream = new FileStream(LogFile, FileMode.Append);
                    _logStreamWriter = new StreamWriterWithTimestamp(_logFileStream)
                    {
                        AutoFlush = true
                    };
                    Console.SetOut(_logStreamWriter);
                    Console.SetError(_logStreamWriter);
                    _date = newDate;
                    CompressOldLogFile();
                }
                else
                {
                    Console.SetOut(DefaultOut);
                    Console.SetError(DefaultError);
                }

                return true;
            }
            catch (IOException e)
            {
                Console.WriteLine(e.ToString());
                return false;
            }
        }

        private static void CloseLogFile()
        {
            _logStreamWriter?.Close();
            _logStreamWriter?.Dispose();
            _logFileStream?.Close();
            _logFileStream?.Dispose();

            _logStreamWriter = null;
            _logFileStream = null;
        }

        public static void Clear()
        {
            CloseLogFile();
            if (LogFile != null)
            {
                File.Delete(LogFile);
            }
            OpenLogFile();
        }

        public static void Error(object o)
        {
            Log(LogLevel.Error, o);
            System.Diagnostics.Debug.WriteLine($@"[{DateTime.Now}] ERROR {o}");
        }

        public static void Info(object o)
        {
            Log(LogLevel.Info, o);
            System.Diagnostics.Debug.WriteLine($@"[{DateTime.Now}] INFO {o}");
        }

        [Conditional("DEBUG")]
        public static void Debug(object o)
        {
            Log(LogLevel.Debug, o);
            System.Diagnostics.Debug.WriteLine($@"[{DateTime.Now}] DEBUG {o}");
        }

        private static string ToString(IEnumerable<StackFrame> stacks)
        {
            return stacks.Aggregate(string.Empty, (current, stack) => current + $@"{stack.GetMethod()}{Environment.NewLine}");
        }

        private static void CompressOldLogFile()
        {
            var list = Directory.GetFiles(Utils.TempPath, @"shadowsocks_*.log", SearchOption.TopDirectoryOnly);
            foreach (var file in list)
            {
                if (file != LogFile)
                {
                    FileManager.ZipCompressToFile(file).ContinueWith(task =>
                    {
                        if (task.Result)
                        {
                            File.Delete(file);
                        }
                    });
                }
            }
        }

        private static void UpdateLogFile()
        {
            if (DateTime.Now.ToString("yyyy-MM") != _date)
            {
                lock (Lock)
                {
                    if (DateTime.Now.ToString("yyyy-MM") != _date)
                    {
                        OpenLogFile();
                    }
                }
            }
        }

        public static void LogUsefulException(Exception e)
        {
            UpdateLogFile();
            // just log useful exceptions, not all of them
            if (e is SocketException se)
            {
                switch (se.SocketErrorCode)
                {
                    case SocketError.ConnectionAborted:
                        // closed by browser when sending
                        // normally happens when download is canceled or a tab is closed before page is loaded
                        break;
                    case SocketError.ConnectionReset:
                        // received rst
                        break;
                    case SocketError.NotConnected:
                        // close when not connected
                        break;
                    case SocketError.Shutdown:
                        // ignore
                        break;
                    case SocketError.Interrupted:
                        // ignore
                        break;
                    default:
                    {
                        if ((uint)se.SocketErrorCode == 0x80004005)
                        {
                            // already closed
                        }
                        else
                        {
                            Error(e);

                            Debug(ToString(new StackTrace().GetFrames()));
                        }
                        break;
                    }
                }
            }
            else
            {
                Error(e);

                Debug(ToString(new StackTrace().GetFrames()));
            }
        }

        public static bool LogSocketException(string remarks, string server, Exception e)
        {
            UpdateLogFile();
            switch (e)
            {
                // just log useful exceptions, not all of them
                case ObfsException oe:
                    Error($@"Proxy server [{remarks}({server})] {oe.Message}");
                    return true;
                case NullReferenceException _:
                case ObjectDisposedException _:
                    return true;
                case SocketException se when se.ErrorCode == 11004:
                    Log(LogLevel.Warn, $@"Proxy server [{remarks}({server})] DNS lookup failed");
                    return true;
                case SocketException se when (uint)se.SocketErrorCode == 0x80004005:
                    // already closed
                    return true;
                case SocketException se:
                    switch (se.SocketErrorCode)
                    {
                        case SocketError.HostNotFound:
                            Log(LogLevel.Warn, $@"Proxy server [{remarks}({server})] Host not found");
                            return true;
                        case SocketError.ConnectionRefused:
                            Log(LogLevel.Warn, $@"Proxy server [{remarks}({server})] connection refused");
                            return true;
                        case SocketError.NetworkUnreachable:
                            Log(LogLevel.Warn, $@"Proxy server [{remarks}({server})] network unreachable");
                            return true;
                        case SocketError.TimedOut:
                        case SocketError.Shutdown:
                            return true;
                    }

                    Log(LogLevel.Info, $@"Proxy server [{remarks}({server})] {Convert.ToString(se.SocketErrorCode)}:{se.Message}");

                    Debug(ToString(new StackTrace().GetFrames()));
                    return true;
                default:
                    return false;
            }
        }

        public static void Log(LogLevel level, object s)
        {
            UpdateLogFile();
            Console.WriteLine($@"[{level}] {s}");
        }

        [Conditional("DEBUG")]
        public static void LogBin(LogLevel level, string info, byte[] data, int length)
        {
            var s = new StringBuilder();
            for (var i = 0; i < length; ++i)
            {
                var fs = $@"0{Convert.ToString(data[i], 16)}";
                s.Append($@" {fs.Substring(fs.Length - 2, 2)}");
            }
            Log(level, $@"{info}{s}");
        }

    }

    // Simply extended System.IO.StreamWriter for adding timestamp workaround
    public class StreamWriterWithTimestamp : StreamWriter
    {
        public StreamWriterWithTimestamp(Stream stream) : base(stream)
        {
        }

        private static string GetTimestamp()
        {
            return $@"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] ";
        }

        public override void WriteLine(string value)
        {
            try
            {
                base.WriteLine(GetTimestamp() + value);
            }
            catch (ObjectDisposedException)
            {

            }
        }

        public override void Write(string value)
        {
            try
            {
                base.Write(GetTimestamp() + value);
            }
            catch (ObjectDisposedException)
            {

            }
        }
    }

}


================================================
FILE: shadowsocks-csharp/Controller/MainController.cs
================================================
using Shadowsocks.Controller.HttpRequest;
using Shadowsocks.Controller.Service;
using Shadowsocks.Enums;
using Shadowsocks.Model;
using Shadowsocks.Model.Transfer;
using Shadowsocks.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Windows;

namespace Shadowsocks.Controller
{
    public class MainController
    {
        // controller:
        // handle user actions
        // manipulates UI
        // interacts with low level logic

        private Listener _listener;
        private List<Listener> _portMapListener;
        private PACDaemon _pacDaemon;
        private PACServer _pacServer;

        private readonly ServerTransferTotal _transfer;
        private HostDaemon _hostDaemon;
        private IPRangeSet _chnRangeSet;
        private HttpProxyRunner _httpProxyRunner;
        private GfwListUpdater _gfwListUpdater;
        private bool _stopped;

        public class PathEventArgs : EventArgs
        {
            public string Path;
        }

        #region Event

        public event EventHandler ConfigChanged;
        public event EventHandler ShowConfigFormEvent;
        public event EventHandler ShowSubscribeWindowEvent;

        // when user clicked Edit PAC, and PAC file has already created
        public event EventHandler<PathEventArgs> PACFileReadyToOpen;
        public event EventHandler<PathEventArgs> UserRuleFileReadyToOpen;

        public event EventHandler<GfwListUpdater.ResultEventArgs> UpdatePACFromGFWListCompleted;

        public event ErrorEventHandler UpdatePACFromGFWListError;

        public event ErrorEventHandler Errored;

        #endregion

        public MainController()
        {
            _transfer = ServerTransferTotal.Load();

            foreach (var server in Global.GuiConfig.Configs)
            {
                if (_transfer.Servers.TryGetValue(server.Id, out var st))
                {
                    var log = new ServerSpeedLog(st.TotalUploadBytes, st.TotalDownloadBytes);
                    server.SpeedLog = log;
                }
            }
        }

        private void ReportError(Exception e)
        {
            Errored?.Invoke(this, new ErrorEventArgs(e));
        }

        private static int FindFirstMatchServer(Server server, IReadOnlyList<Server> servers)
        {
            for (var i = 0; i < servers.Count; ++i)
            {
                if (server.IsMatchServer(servers[i]))
                {
                    return i;
                }
            }
            return -1;
        }

        private static void AppendConfiguration(Configuration mergeConfig, IReadOnlyList<Server> servers)
        {
            if (servers != null)
            {
                Application.Current.Dispatcher?.InvokeAsync(() =>
                {
                    foreach (var server in servers)
                    {
                        if (FindFirstMatchServer(server, mergeConfig.Configs) == -1)
                        {
                            mergeConfig.Configs.Add(server);
                        }
                    }
                });
            }
        }

        private static IEnumerable<Server> MergeConfiguration(Configuration mergeConfig, IReadOnlyList<Server> servers)
        {
            if (servers != null)
            {
                foreach (var server in servers)
                {
                    var i = FindFirstMatchServer(server, mergeConfig.Configs);
                    if (i != -1)
                    {
                        var enable = server.Enable;
                        server.CopyServer(mergeConfig.Configs[i]);
                        server.Enable = enable;
                    }
                }
            }

            return from t in mergeConfig.Configs let j = FindFirstMatchServer(t, servers) where j == -1 select t;
        }

        private static Configuration MergeGetConfiguration(Configuration mergeConfig)
        {
            var ret = Global.Load();
            if (mergeConfig != null)
            {
                MergeConfiguration(mergeConfig, ret.Configs);
            }
            return ret;
        }

        /// <summary>
        /// 从配置文件导入服务器
        /// </summary>
        /// <param name="mergeConfig"></param>
        public void MergeConfiguration(Configuration mergeConfig)
        {
            AppendConfiguration(Global.GuiConfig, mergeConfig.Configs);
            SaveAndReload();
        }

        public void SaveServersConfig(Configuration config, bool reload)
        {
            var missingServers = MergeConfiguration(Global.GuiConfig, config.Configs);
            Global.GuiConfig.CopyFrom(config);
            foreach (var s in missingServers)
            {
                s.Connections.CloseAll();
            }

            if (reload)
            {
                SaveAndReload();
            }
            else
            {
                SaveAndNotifyChanged();
            }
        }

        public void SaveServersPortMap(Configuration config)
        {
            StopPortMap();
            Global.GuiConfig.PortMap = config.PortMap;
            Global.GuiConfig.FlushPortMapCache();
            LoadPortMap();
            SaveAndNotifyChanged();
        }

        /// <summary>
        /// 选择指定服务器
        /// </summary>
        public void SelectServerIndex(int index)
        {
            Global.GuiConfig.Index = index;
            SaveAndNotifyChanged();
        }

        /// <summary>
        /// 导入服务器链接
        /// </summary>
        public bool AddServerBySsUrl(string ssUrLs, string force_group = null, bool toLast = false)
        {
            try
            {
                var urls = ssUrLs.GetLines().Reverse();
                var i = 0;
                foreach (var url in urls.Select(url => url.Trim('/')).Where(url => url.StartsWith(@"ss://", StringComparison.OrdinalIgnoreCase) || url.StartsWith(@"ssr://", StringComparison.OrdinalIgnoreCase)))
                {
                    ++i;
                    var server = new Server(url, force_group);
                    if (toLast)
                    {
                        Global.GuiConfig.Configs.Add(server);
                    }
                    else
                    {
                        var index = Global.GuiConfig.Index + 1;
                        if (index < 0 || index > Global.GuiConfig.Configs.Count)
                        {
                            index = Global.GuiConfig.Configs.Count;
                        }

                        Global.GuiConfig.Configs.Insert(index, server);
                    }
                }
                if (i > 0)
                {
                    SaveAndReload();
                    return true;
                }
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
                return false;
            }
            return false;
        }

        /// <summary>
        /// 导入订阅链接
        /// </summary>
        public bool AddSubscribeUrl(string str)
        {
            try
            {
                var urls = str.GetLines();
                var newSubscribes = new List<ServerSubscribe>();
                var existSubscribes = new List<ServerSubscribe>();
                foreach (var url in urls.Where(url => url.StartsWith(@"sub://", StringComparison.OrdinalIgnoreCase)))
                {
                    var sub = Regex.Match(url, "sub://([A-Za-z0-9_-]+)", RegexOptions.IgnoreCase);
                    if (sub.Success)
                    {
                        var res = Base64.DecodeUrlSafeBase64(sub.Groups[1].Value);
                        if (Global.GuiConfig.ServerSubscribes.All(serverSubscribe => serverSubscribe.Url != res))
                        {
                            var newSub = new ServerSubscribe { Url = res };
                            newSubscribes.Add(newSub);
                            Global.GuiConfig.ServerSubscribes.Add(newSub);
                        }
                        else
                        {
                            existSubscribes.Add(Global.GuiConfig.ServerSubscribes.Find(serverSubscribe => serverSubscribe.Url == res));
                        }
                    }
                }
                if (newSubscribes.Count > 0)
                {
                    SaveAndNotifyChanged();
                    Global.UpdateSubscribeManager.CreateTask(Global.GuiConfig, Global.UpdateNodeChecker, true, newSubscribes);
                    return true;
                }
                if (existSubscribes.Count > 0)
                {
                    Global.UpdateSubscribeManager.CreateTask(Global.GuiConfig, Global.UpdateNodeChecker, true, existSubscribes);
                    return false;
                }
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
                return false;
            }
            return false;
        }

        /// <summary>
        /// 切换系统代理模式
        /// </summary>
        public void ToggleMode(ProxyMode mode)
        {
            ProxyMode oldMode = Global.GuiConfig.SysProxyMode;
            Global.GuiConfig.SysProxyMode = mode;
            ReloadPacServer();
            if (oldMode is not ProxyMode.NoModify && mode is ProxyMode.NoModify)
            {
                SystemProxy.Restore();
            }
            else
            {
                UpdateSystemProxy();
            }
            SaveAndNotifyChanged();
        }

        /// <summary>
        /// 切换代理规则
        /// </summary>
        /// <param name="mode"></param>
        public void ToggleRuleMode(ProxyRuleMode mode)
        {
            Global.GuiConfig.ProxyRuleMode = mode;
            SaveAndNotifyChanged();
        }

        public void ToggleSelectRandom(bool enabled)
        {
            Global.GuiConfig.Random = enabled;
            if (!enabled)
            {
                DisconnectAllConnections(true);
            }
            SaveAndNotifyChanged();
        }

        public void ToggleSameHostForSameTargetRandom(bool enabled)
        {
            Global.GuiConfig.SameHostForSameTarget = enabled;
            SaveAndNotifyChanged();
        }

        public void ToggleSelectAutoCheckUpdate(bool enabled)
        {
            Global.GuiConfig.AutoCheckUpdate = enabled;
            Global.SaveConfig();
        }

        public void ToggleSelectAllowPreRelease(bool enabled)
        {
            Global.GuiConfig.IsPreRelease = enabled;
            Global.SaveConfig();
        }

        /// <summary>
        /// 保存配置文件并通知配置改变
        /// </summary>
        public void SaveAndNotifyChanged()
        {
            Global.SaveConfig();
            Application.Current.Dispatcher?.InvokeAsync(() => { ConfigChanged?.Invoke(this, EventArgs.Empty); });
        }

        /// <summary>
        /// 保存配置文件并重载
        /// </summary>
        private void SaveAndReload()
        {
            Global.SaveConfig();
            Reload();
        }

        private void StopPortMap()
        {
            if (_portMapListener != null)
            {
                foreach (var l in _portMapListener)
                {
                    l.Stop();
                }

                _portMapListener = null;
            }
        }

        private void LoadPortMap()
        {
            _portMapListener = new List<Listener>();
            foreach (var pair in Global.GuiConfig.PortMapCache)
            {
                try
                {
                    var local = new Local(Global.GuiConfig, _transfer, _chnRangeSet);
                    var services = new List<Listener.IService> { local };
                    var listener = new Listener(services);
                    listener.Start(Global.GuiConfig, pair.Key);
                    _portMapListener.Add(listener);
                }
                catch (Exception e)
                {
                    ThrowSocketException(ref e);
                    Logging.LogUsefulException(e);
                    ReportError(e);
                }
            }
        }

        public void Stop()
        {
            if (_stopped)
            {
                return;
            }
            _stopped = true;

            StopPortMap();

            _listener?.Stop();
            _httpProxyRunner?.Stop();
            if (Global.GuiConfig.SysProxyMode is not ProxyMode.NoModify)
            {
                SystemProxy.Restore();
            }
            ServerTransferTotal.Save(_transfer, Global.GuiConfig.Configs);
        }

        public void ClearTransferTotal(string serverId)
        {
            _transfer.Clear(serverId);
            var server = Global.GuiConfig.Configs.Find(s => s.Id == serverId);
            server?.SpeedLog.ClearTrans();
        }

        public void TouchPACFile()
        {
            PACFileReadyToOpen?.Invoke(this, new PathEventArgs { Path = _pacDaemon.TouchPACFile() });
        }

        public void TouchUserRuleFile()
        {
            UserRuleFileReadyToOpen?.Invoke(this, new PathEventArgs { Path = _pacDaemon.TouchUserRuleFile() });
        }

        public void UpdatePACFromGFWList()
        {
            _gfwListUpdater?.UpdatePacFromGfwList(Global.GuiConfig);
        }

        public void UpdatePACFromOnlinePac(string url)
        {
            _gfwListUpdater?.UpdateOnlinePac(Global.GuiConfig, url);
        }

        private void ReloadPacServer()
        {
            if (_pacDaemon == null)
            {
                _pacDaemon = new PACDaemon();
                _pacDaemon.PACFileChanged += (o, args) =>
                {
                    _pacServer?.UpdatePacUrl(Global.GuiConfig);
                    UpdateSystemProxy();
                };
                _pacDaemon.UserRuleFileChanged += PacDaemon_UserRuleFileChanged;
            }

            if (_pacServer == null)
            {
                _pacServer = new PACServer(_pacDaemon);
            }

            _pacServer.UpdatePacUrl(Global.GuiConfig);
        }

        private void ReloadIPRange()
        {
            _chnRangeSet = new IPRangeSet();
            _chnRangeSet.LoadChn();
        }

        private void ReloadProxyRule()
        {
            if (_hostDaemon == null)
            {
                _hostDaemon = new HostDaemon();
                _hostDaemon.ChnIpChanged += (o, args) => ReloadIPRange();
                _hostDaemon.UserRuleChanged += (o, args) => HostMap.Reload();
            }

            ReloadIPRange();
            HostMap.Reload();
        }

        public void Reload()
        {
            StopPortMap();
            // some logic in configuration updated the config when saving, we need to read it again
            Global.GuiConfig = MergeGetConfiguration(Global.GuiConfig);
            Global.GuiConfig.FlushPortMapCache();
            Logging.SaveToFile = Global.GuiConfig.LogEnable;
            Logging.OpenLogFile();

            ReloadProxyRule();

            _httpProxyRunner ??= new HttpProxyRunner();
            ReloadPacServer();
            if (_gfwListUpdater == null)
            {
                _gfwListUpdater = new GfwListUpdater();
                _gfwListUpdater.UpdateCompleted += (o, args) => UpdatePACFromGFWListCompleted?.Invoke(o, args);
                _gfwListUpdater.Error += (o, args) => UpdatePACFromGFWListError?.Invoke(o, args);
            }

            _listener?.Stop();
            _httpProxyRunner.Stop();
            try
            {
                _httpProxyRunner.Start(Global.GuiConfig);

                var local = new Local(Global.GuiConfig, _transfer, _chnRangeSet);
                var services = new List<Listener.IService>
                {
                    local,
                    _pacServer,
                    new HttpPortForwarder(_httpProxyRunner.RunningPort, Global.GuiConfig)
                };
                _listener = new Listener(services);
                _listener.Start(Global.GuiConfig, 0);
            }
            catch (Exception e)
            {
                ThrowSocketException(ref e);
                Logging.LogUsefulException(e);
                ReportError(e);
            }

            LoadPortMap();

            Application.Current.Dispatcher?.InvokeAsync(() => { ConfigChanged?.Invoke(this, EventArgs.Empty); });

            UpdateSystemProxy();
        }

        private static void ThrowSocketException(ref Exception e)
        {
            // TODO:translate Microsoft language into human language
            // i.e. An attempt was made to access a socket in a way forbidden by its access permissions => Port already in use
            // https://docs.microsoft.com/zh-cn/dotnet/api/system.net.sockets.socketerror
            if (e is not SocketException se)
            {
                return;
            }

            switch (se.SocketErrorCode)
            {
                case SocketError.AddressAlreadyInUse:
                {
                    e = new Exception(string.Format(I18NUtil.GetAppStringValue(@"PortInUse"), Global.GuiConfig.LocalPort), se);
                    break;
                }
                case SocketError.AccessDenied:
                {
                    e = new Exception(string.Format(I18NUtil.GetAppStringValue(@"PortReserved"), Global.GuiConfig.LocalPort), se);
                    break;
                }
            }
        }

        private void UpdateSystemProxy()
        {
            SystemProxy.Update(Global.GuiConfig, _pacServer);
        }

        private void PacDaemon_UserRuleFileChanged(object sender, EventArgs e)
        {
            if (!Utils.IsGFWListPAC(PACDaemon.PAC_FILE))
            {
                return;
            }
            if (!File.Exists(Utils.GetTempPath(PACServer.gfwlist_FILE)))
            {
                UpdatePACFromGFWList();
            }
            else
            {
                GfwListUpdater.MergeAndWritePacFile(FileManager.NonExclusiveReadAllText(Utils.GetTempPath(PACServer.gfwlist_FILE)));
            }

            UpdateSystemProxy();
        }

        public void ShowConfigForm(int? index = null)
        {
            ShowConfigFormEvent?.Invoke(index, EventArgs.Empty);
        }

        public void ShowSubscribeWindow()
        {
            ShowSubscribeWindowEvent?.Invoke(default, EventArgs.Empty);
        }

        /// <summary>
        /// Disconnect all connections from the remote host.
        /// </summary>
        public void DisconnectAllConnections(bool checkSwitchAutoCloseAll = false)
        {
            var config = Global.GuiConfig;
            if (checkSwitchAutoCloseAll && !config.CheckSwitchAutoCloseAll)
            {
                Console.WriteLine(@"config.checkSwitchAutoCloseAll:False");
                return;
            }
            foreach (var server in config.Configs)
            {
                server.Connections.CloseAll();
            }
        }

        public void CopyPacUrl()
        {
            Clipboard.SetDataObject(_pacServer.PacUrl);
        }
    }
}


================================================
FILE: shadowsocks-csharp/Controller/MenuViewController.cs
================================================
using Hardcodet.Wpf.TaskbarNotification;
using Microsoft.Win32;
using Shadowsocks.Controller.HttpRequest;
using Shadowsocks.Controller.Service;
using Shadowsocks.Enums;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using Shadowsocks.View;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Shapes;
using Brushes = System.Windows.Media.Brushes;
using Rectangle = System.Drawing.Rectangle;

namespace Shadowsocks.Controller
{
    public class MenuViewController
    {
        private class EventParams
        {
            public readonly object sender;
            public readonly EventArgs e;

            public EventParams(object sender, EventArgs e)
            {
                this.sender = sender;
                this.e = e;
            }
        }

        // yes this is just a menu view controller
        // when config form is closed, it moves away from RAM
        // and it should just do anything related to the config form

        private readonly MainController controller;
        private readonly HttpRequest.UpdateChecker updateChecker;

        private readonly TaskbarIcon _notifyIcon;
        private ContextMenu _contextMenu;

        private MenuItem noModifyItem;
        private MenuItem enableItem;
        private MenuItem PACModeItem;
        private MenuItem globalModeItem;

        private MenuItem ruleBypassLan;
        private MenuItem ruleBypassChina;
        private MenuItem ruleBypassNotChina;
        private MenuItem ruleUser;
        private MenuItem ruleDisableBypass;

        private Separator SeparatorItem;
        private MenuItem ServersItem;
        private MenuItem SelectRandomItem;
        private MenuItem sameHostForSameTargetItem;
        private MenuItem _moreMenu;
        private MenuItem _updateMenu;
        private MenuItem UpdateItem;
        private MenuItem AutoCheckUpdateItem;
        private MenuItem AllowPreReleaseItem;
        private ServerConfigWindow _serverConfigWindow;
        private SettingsWindow _settingsWindow;
        private DnsSettingWindow _dnsSettingsWindow;

        #region ServerLogWindow

        private ServerLogWindow _serverLogWindow;
        private WindowStatus _serverLogWindowStatus;

        #endregion

        private PortSettingsWindow _portMapWindow;
        private SubscribeWindow _subScribeWindow;
        private LogWindow _logWindow;
        private string _urlToOpen;
        private System.Timers.Timer timerDelayCheckUpdate;

        private bool configFrom_open;
        private readonly List<EventParams> eventList = new();

        public MenuViewController(MainController controller)
        {
            this.controller = controller;

            LoadMenu();

            controller.ConfigChanged += controller_ConfigChanged;
            controller.PACFileReadyToOpen += controller_FileReadyToOpen;
            controller.UserRuleFileReadyToOpen += controller_FileReadyToOpen;
            controller.Errored += ControllerError;
            controller.UpdatePACFromGFWListCompleted += controller_UpdatePACFromGFWListCompleted;
            controller.UpdatePACFromGFWListError += controller_UpdatePACFromGFWListError;
            controller.ShowConfigFormEvent += Config_Click;
            controller.ShowSubscribeWindowEvent += Controller_ShowSubscribeWindowEvent;

            _notifyIcon = new TaskbarIcon();
            UpdateTrayIcon();
            _notifyIcon.Visibility = Visibility.Visible;
            _notifyIcon.ContextMenu = _contextMenu;

            _notifyIcon.TrayLeftMouseUp += notifyIcon_TrayLeftMouseUp;
            _notifyIcon.TrayMiddleMouseUp += notifyIcon_TrayMiddleMouseUp;
            _notifyIcon.TrayBalloonTipClicked += notifyIcon_TrayBalloonTipClicked;

            updateChecker = new HttpRequest.UpdateChecker();
            updateChecker.NewVersionFound += updateChecker_NewVersionFound;
            updateChecker.NewVersionNotFound += updateChecker_NewVersionNotFound;
            updateChecker.NewVersionFoundFailed += UpdateChecker_NewVersionFoundFailed;

            Global.UpdateNodeChecker = new UpdateNode();
            Global.UpdateNodeChecker.NewFreeNodeFound += UpdateNodeCheckerNewNodeFound;

            Global.UpdateSubscribeManager = new UpdateSubscribeManager();

            LoadCurrentConfiguration();

            timerDelayCheckUpdate = new System.Timers.Timer(1000.0 * 10);
            timerDelayCheckUpdate.Elapsed += timer_Elapsed;
            timerDelayCheckUpdate.Start();
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            timerDelayCheckUpdate.Interval = 1000.0 * 60 * 60 * 1;// 1 hour

            var cfg = Global.GuiConfig;
            if (cfg.AutoCheckUpdate)
            {
                updateChecker.Check(cfg, false);
            }

            Global.UpdateSubscribeManager.CreateTask(cfg, Global.UpdateNodeChecker, false);
        }

        private static void ControllerError(object sender, ErrorEventArgs e)
        {
            MessageBox.Show(e.GetException().ToString(), string.Format(I18NUtil.GetAppStringValue(@"ControllerError"), e.GetException().Message));
        }

        private void UpdateTrayIcon()
        {
            var config = Global.GuiConfig;
            var enabled = config.SysProxyMode is not ProxyMode.NoModify and not ProxyMode.Direct;
            var global = config.SysProxyMode == ProxyMode.Global;
            var random = config.Random;

            var colorMask = ViewUtils.SelectColorMask(enabled, global);
            var icon = ViewUtils.ChangeBitmapColor(Resources.ss128, colorMask, random);
            var size = ViewUtils.GetIconSize();
            var newIcon = Icon.FromHandle(ViewUtils.ResizeBitmap(icon, size.Width, size.Height).GetHicon());

            if (_notifyIcon.Icon != null)
            {
                ViewUtils.DestroyIcon(_notifyIcon.Icon.Handle);
            }

            _notifyIcon.Icon = newIcon;

            string strServer = null;
            var line3 = string.Empty;
            var line4 = string.Empty;
            if (random)
            {
                strServer = $@"{I18NUtil.GetAppStringValue(@"LoadBalance")}{I18NUtil.GetAppStringValue(@"Colon")}{I18NUtil.GetAppStringValue(config.BalanceType.ToString())}";
                if (config.RandomInGroup)
                {
                    line3 = $@"{I18NUtil.GetAppStringValue(@"BalanceInGroup")}{Environment.NewLine}";
                }

                if (config.AutoBan)
                {
                    line4 = $@"{I18NUtil.GetAppStringValue(@"AutoBan")}{Environment.NewLine}";
                }
            }
            else
            {
                if (config.Index >= 0 && config.Index < config.Configs.Count)
                {
                    var groupName = config.Configs[config.Index].Group;
                    var serverName = config.Configs[config.Index].Remarks;
                    if (string.IsNullOrWhiteSpace(groupName))
                    {
                        strServer = string.IsNullOrWhiteSpace(serverName) ? null : serverName;
                    }
                    else if (string.IsNullOrWhiteSpace(serverName))
                    {
                        strServer = $@"{groupName}";
                    }
                    else
                    {
                        strServer = $@"{groupName}{I18NUtil.GetAppStringValue(@"Colon")}{serverName}";
                    }
                }
            }

            string line1;
            switch (config.SysProxyMode)
            {
                case ProxyMode.NoModify:
                {
                    line1 = $@"{I18NUtil.GetAppStringValue(@"NoProxy")}{Environment.NewLine}";
                    break;
                }
                case ProxyMode.Direct:
                {
                    line1 = $@"{I18NUtil.GetAppStringValue(@"DisableProxy")}{Environment.NewLine}";
                    break;
                }
                case ProxyMode.Pac:
                {
                    line1 = $@"{I18NUtil.GetAppStringValue(@"PacProxy")}{Environment.NewLine}";
                    break;
                }
                case ProxyMode.Global:
                {
                    line1 = $@"{I18NUtil.GetAppStringValue(@"GlobalProxy")}{Environment.NewLine}";
                    break;
                }
                default:
                {
                    line1 = null;
                    break;
                }
            }
            var line2 = string.IsNullOrWhiteSpace(strServer) ? null : $@"{strServer}{Environment.NewLine}";
            var line5 = string.Format(I18NUtil.GetAppStringValue(@"RunningPort"), config.LocalPort); // this feedback is very important because they need to know Shadowsocks is running

            var text = $@"{line1}{line2}{line3}{line4}{line5}";
            _notifyIcon.ToolTipText = text;
        }

        private void LoadMenu()
        {
            if (Application.Current.FindResource(@"SysTrayMenu") is ContextMenu menu)
            {
                _contextMenu = menu;
            }

            I18NUtil.SetLanguage(_contextMenu);
            foreach (var obj in _contextMenu.Items)
            {
                if (obj is MenuItem menuItem)
                {
                    switch (menuItem.Name)
                    {
                        case @"Mode":
                        {
                            enableItem = (MenuItem)menuItem.Items[0];
                            PACModeItem = (MenuItem)menuItem.Items[1];
                            globalModeItem = (MenuItem)menuItem.Items[2];
                            noModifyItem = (MenuItem)menuItem.Items[4];
                            enableItem.Click += EnableItem_Click;
                            PACModeItem.Click += PACModeItem_Click;
                            globalModeItem.Click += GlobalModeItem_Click;
                            noModifyItem.Click += NoModifyItem_Click;
                            break;
                        }
                        case @"ProxySetting":
                        {
                            var pacMenuItem = (MenuItem)menuItem.Items[0];
                            var proxyMenuItem = (MenuItem)menuItem.Items[1];
                            ((MenuItem)menuItem.Items[3]).Click += CopyPacUrlItem_Click;
                            ((MenuItem)menuItem.Items[4]).Click += EditPACFileItem_Click;
                            ((MenuItem)menuItem.Items[5]).Click += EditUserRuleFileForGFWListItem_Click;

                            ((MenuItem)pacMenuItem.Items[0]).Click += UpdatePACFromLanIPListItem_Click;

                            ((MenuItem)pacMenuItem.Items[2]).Click += UpdatePACFromCNWhiteListItem_Click;
                            ((MenuItem)pacMenuItem.Items[3]).Click += UpdatePACFromCnWhiteListIpItem_Click;
                            ((MenuItem)pacMenuItem.Items[4]).Click += UpdatePACFromChnIpItem_Click;
                            ((MenuItem)pacMenuItem.Items[5]).Click += UpdatePACFromGFWListItem_Click;

                            ((MenuItem)pacMenuItem.Items[7]).Click += UpdatePACFromCNOnlyListItem_Click;

                            ruleBypassLan = (MenuItem)proxyMenuItem.Items[0];
                            ruleBypassChina = (MenuItem)proxyMenuItem.Items[1];
                            ruleBypassNotChina = (MenuItem)proxyMenuItem.Items[2];
                            ruleUser = (MenuItem)proxyMenuItem.Items[3];
                            ruleDisableBypass = (MenuItem)proxyMenuItem.Items[5];

                            ruleBypassLan.Click += RuleBypassLanItem_Click;
                            ruleBypassChina.Click += RuleBypassChinaItem_Click;
                            ruleBypassNotChina.Click += RuleBypassNotChinaItem_Click;
                            ruleUser.Click += RuleUserItem_Click;
                            ruleDisableBypass.Click += RuleBypassDisableItem_Click;
                            break;
                        }
                        case @"Servers":
                        {
                            ServersItem = menuItem;
                            SeparatorItem = (Separator)menuItem.Items[0];
                            SelectRandomItem = (MenuItem)menuItem.Items[7];
                            sameHostForSameTargetItem = (MenuItem)menuItem.Items[8];

                            ((MenuItem)menuItem.Items[1]).Click += Config_Click;
                            ((MenuItem)menuItem.Items[3]).Click += ScanQRCodeItem_Click;
                            ((MenuItem)menuItem.Items[4]).Click += ImportAddressFromClipboard_Click;
                            ((MenuItem)menuItem.Items[5]).Click += Import_Click;
                            SelectRandomItem.Click += SelectRandomItem_Click;
                            sameHostForSameTargetItem.Click += SelectSameHostForSameTargetItem_Click;
                            ((MenuItem)menuItem.Items[10]).Click += ShowServerLogItem_Click;
                            ((MenuItem)menuItem.Items[11]).Click += DisconnectCurrent_Click;
                            break;
                        }
                        case @"ServersSubscribe":
                        {
                            ((MenuItem)menuItem.Items[0]).Click += SubscribeSetting_Click;
                            ((MenuItem)menuItem.Items[1]).Click += CheckNodeUpdate_Click;
                            break;
                        }
                        case @"ShowLogs":
                        {
                            menuItem.Click += ShowLogItem_Click;
                            break;
                        }
                        case @"More":
                        {
                            _moreMenu = menuItem;
                            ((MenuItem)_moreMenu.Items[0]).Click += Setting_Click;
                            ((MenuItem)_moreMenu.Items[1]).Click += DnsSetting_Click;
                            ((MenuItem)_moreMenu.Items[2]).Click += ShowPortMapItem_Click;
                            ((MenuItem)_moreMenu.Items[3]).Click += ShowUrlFromQrCode;
                            ((MenuItem)_moreMenu.Items[5]).Click += OpenWiki_Click;
                            ((MenuItem)_moreMenu.Items[6]).Click += FeedbackItem_Click;

                            _updateMenu = (MenuItem)_moreMenu.Items[8];

                            ((MenuItem)_updateMenu.Items[0]).Click += CheckUpdate_Click;
                            UpdateItem = (MenuItem)_updateMenu.Items[1];
                            AutoCheckUpdateItem = (MenuItem)_updateMenu.Items[3];
                            AllowPreReleaseItem = (MenuItem)_updateMenu.Items[4];
                            UpdateItem.Click += UpdateItem_Clicked;
                            AutoCheckUpdateItem.Click += AutoCheckUpdateItem_Click;
                            AllowPreReleaseItem.Click += AllowPreRelease_Click;
                            break;
                        }
                        case @"Quit":
                        {
                            menuItem.Click += Quit_Click;
                            break;
                        }
                    }
                }
            }
        }

        private void controller_ConfigChanged(object sender, EventArgs e)
        {
            LoadCurrentConfiguration();
            UpdateTrayIcon();
        }

        private void controller_FileReadyToOpen(object sender, MainController.PathEventArgs e)
        {
            Utils.OpenURL(e.Path);
        }

        private void controller_UpdatePACFromGFWListError(object sender, ErrorEventArgs e)
        {
            _notifyIcon.ShowBalloonTip(I18NUtil.GetAppStringValue(@"UpdatePacFailed"), e.GetException().Message, BalloonIcon.Error);
            Logging.LogUsefulException(e.GetException());
        }

        private void controller_UpdatePACFromGFWListCompleted(object sender, GfwListUpdater.ResultEventArgs e)
        {
            var result = e.Success ?
                    e.PacType == PacType.GfwList ?
                    I18NUtil.GetAppStringValue(@"GfwListPacUpdated") : I18NUtil.GetAppStringValue(@"PacUpdated")
                : I18NUtil.GetAppStringValue(@"GfwListPacNotFound");
            _notifyIcon.ShowBalloonTip(HttpRequest.UpdateChecker.Name, result, BalloonIcon.Info);
        }

        private void UpdateNodeCheckerNewNodeFound(object sender, EventArgs e)
        {
            if (configFrom_open)
            {
                eventList.Add(new EventParams(sender, e));
                return;
            }
            string lastGroup = null;
            var count = 0;
            if (!string.IsNullOrWhiteSpace(Global.UpdateNodeChecker.FreeNodeResult))
            {
                Global.UpdateNodeChecker.FreeNodeResult = Global.UpdateNodeChecker.FreeNodeResult.TrimEnd('\r', '\n', ' ');
                var config = Global.GuiConfig;
                var selectedServer = config.Configs.ElementAtOrDefault(config.Index);
                try
                {
                    Global.UpdateNodeChecker.FreeNodeResult = Base64.DecodeBase64(Global.UpdateNodeChecker.FreeNodeResult);
                }
                catch
                {
                    Global.UpdateNodeChecker.FreeNodeResult = string.Empty;
                }
                var urls = Global.UpdateNodeChecker.FreeNodeResult.GetLines().ToList();
                urls.RemoveAll(url => !url.StartsWith(@"ssr://"));
                if (urls.Count > 0)
                {
                    lastGroup = Global.UpdateSubscribeManager.CurrentServerSubscribe.OriginTag;
                    if (string.IsNullOrEmpty(lastGroup))
                    {
                        foreach (var url in urls)
                        {
                            try // try get group name
                            {
                                var server = new Server(url, null);
                                if (!string.IsNullOrEmpty(server.Group))
                                {
                                    if (config.ServerSubscribes.Any(subscribe => subscribe.Tag == server.Group))
                                    {
                                        continue;
                                    }

                                    var serverSubscribe = config.ServerSubscribes.Find(sub =>
                                    sub.Url == Global.UpdateSubscribeManager.CurrentServerSubscribe.Url
                                    && string.IsNullOrEmpty(sub.OriginTag));

                                    if (serverSubscribe != null)
                                    {
                                        lastGroup = serverSubscribe.Tag = server.Group;
                                    }

                                    break;
                                }
                            }
                            catch
                            {
                                // ignored
                            }
                        }
                    }
                    if (string.IsNullOrEmpty(lastGroup))
                    {
                        lastGroup = Global.UpdateSubscribeManager.CurrentServerSubscribe.UrlMd5;
                    }

                    //Find old servers
                    var firstInsertIndex = config.Configs.Count;
                    var oldServers = config.Configs.FindAll(server => server.SubTag == lastGroup);
                    var index = config.Configs.FindIndex(server => server.SubTag == lastGroup);
                    if (index >= 0)
                    {
                        firstInsertIndex = index;
                    }

                    //Find new servers
                    var newServers = new List<Server>();
                    foreach (var url in urls)
                    {
                        try
                        {
                            var server = new Server(url, lastGroup) { Index = firstInsertIndex++ };
                            newServers.Add(server);
                        }
                        catch
                        {
                            // ignored
                        }
                    }

                    //Group name is not empty
                    foreach (var newServer in newServers.Where(newServer => string.IsNullOrEmpty(newServer.Group)))
                    {
                        newServer.Group = lastGroup;
                    }

                    count = newServers.Count;

                    var removeServers = oldServers.Except(newServers);
                    var addServers = newServers.Except(oldServers);

                    //Remove servers
                    foreach (var server in removeServers)
                    {
                        server.Connections.CloseAll();
                        config.Configs.Remove(server);
                    }

                    //Add servers
                    foreach (var server in addServers)
                    {
                        if (server.Index > config.Configs.Count)
                        {
                            server.Index = config.Configs.Count;
                        }
                        config.Configs.Insert(server.Index, server);
                    }

                    //Set SelectedServer
                    var selectedIndex = -1;
                    if (selectedServer is not null)
                    {
                        selectedIndex = config.Configs.FindIndex(server => server.Id == selectedServer.Id);

                        if (selectedIndex < 0)
                        {
                            selectedIndex = config.Configs.FindIndex(server =>
                                server.SubTag == selectedServer.SubTag && server.IsMatchServer(selectedServer)
                            );
                        }

                        if (selectedIndex < 0)
                        {
                            selectedIndex = config.Configs.FindIndex(server =>
                                server.SubTag == selectedServer.SubTag
                                && server.Group == selectedServer.Group
                                && server.Remarks == selectedServer.Remarks
                            );
                        }

                        if (selectedIndex < 0)
                        {
                            selectedIndex = config.Configs.FindIndex(server =>
                                server.SubTag == selectedServer.SubTag
                                && server.Group == selectedServer.Group
                            );
                        }

                        if (selectedIndex < 0)
                        {
                            selectedIndex = config.Configs.FindIndex(server => server.SubTag == selectedServer.SubTag);
                        }
                    }

                    config.Index = selectedIndex < 0 ? default : selectedIndex;

                    //If Update Success
                    if (count > 0)
                    {
                        foreach (var serverSubscribe in config.ServerSubscribes.Where(serverSubscribe => serverSubscribe.Url == Global.UpdateNodeChecker.SubscribeTask.Url))
                        {
                            serverSubscribe.LastUpdateTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                        }

                        var defaultServer = new Server();
                        config.Configs.RemoveAll(server => server.IsMatchServer(defaultServer));
                    }
                    controller.SaveServersConfig(config, true);
                }
            }

            if (count > 0)
            {
                if (Global.UpdateNodeChecker.Notify)
                {
                    _notifyIcon.ShowBalloonTip(I18NUtil.GetAppStringValue(@"Success"), string.Format(I18NUtil.GetAppStringValue(@"UpdateSubscribeSuccess"), lastGroup), BalloonIcon.Info);
                }
            }
            else
            {
                if (string.IsNullOrEmpty(lastGroup))
                {
                    lastGroup = Global.UpdateNodeChecker.SubscribeTask.Tag;
                }

                if (Global.UpdateNodeChecker.Notify)
                {
                    _notifyIcon.ShowBalloonTip(I18NUtil.GetAppStringValue(@"Error"), string.Format(I18NUtil.GetAppStringValue(@"UpdateSubscribeFailure"), lastGroup), BalloonIcon.Info);
                }
            }

            Global.UpdateSubscribeManager.Next();
        }

        private void updateChecker_NewVersionFound(object sender, EventArgs e)
        {
            Application.Current.Dispatcher?.InvokeAsync(() =>
            {
                if (updateChecker.Found)
                {
                    if (UpdateItem.Visibility != Visibility.Visible)
                    {
                        _notifyIcon.ShowBalloonTip(
                                string.Format(I18NUtil.GetAppStringValue(@"NewVersionFound"),
                                        HttpRequest.UpdateChecker.Name, updateChecker.LatestVersionNumber),
                                I18NUtil.GetAppStringValue(@"ClickMenuToDownload"), BalloonIcon.Info);
                    }
                    _moreMenu.Icon = CreateSelectedIcon();
                    _updateMenu.Icon = CreateSelectedIcon();
                    UpdateItem.Visibility = Visibility.Visible;
                    UpdateItem.Header = string.Format(I18NUtil.GetAppStringValue(@"NewVersionAvailable"),
                            HttpRequest.UpdateChecker.Name, updateChecker.LatestVersionNumber);
                }
            });
        }

        private void updateChecker_NewVersionNotFound(object sender, EventArgs e)
        {
            _notifyIcon.ShowBalloonTip($@"{HttpRequest.UpdateChecker.Name} {HttpRequest.UpdateChecker.FullVersion}",
            $@"{I18NUtil.GetAppStringValue(@"NewVersionNotFound")}{Environment.NewLine}{HttpRequest.UpdateChecker.Version}≥{updateChecker.LatestVersionNumber}",
            BalloonIcon.Info);
        }

        private void UpdateChecker_NewVersionFoundFailed(object sender, EventArgs e)
        {
            _notifyIcon.ShowBalloonTip($@"{HttpRequest.UpdateChecker.Name} {HttpRequest.UpdateChecker.FullVersion}", I18NUtil.GetAppStringValue(@"NewVersionFoundFailed"), BalloonIcon.Info);
        }

        private void UpdateItem_Clicked(object sender, RoutedEventArgs e)
        {
            Utils.OpenURL(updateChecker.LatestVersionUrl);
            _moreMenu.Icon = null;
            _updateMenu.Icon = null;
            UpdateItem.Visibility = Visibility.Collapsed;
            updateChecker.Found = false;
        }

        private void notifyIcon_TrayBalloonTipClicked(object sender, RoutedEventArgs e)
        {
            var url = updateChecker.LatestVersionUrl;
            if (!string.IsNullOrWhiteSpace(url))
            {
                Utils.OpenURL(url);
            }
        }

        private void UpdateSysProxyMode(Configuration config)
        {
            noModifyItem.IsChecked = config.SysProxyMode == ProxyMode.NoModify;
            enableItem.IsChecked = config.SysProxyMode == ProxyMode.Direct;
            PACModeItem.IsChecked = config.SysProxyMode == ProxyMode.Pac;
            globalModeItem.IsChecked = config.SysProxyMode == ProxyMode.Global;
        }

        private void UpdateProxyRule(Configuration config)
        {
            ruleDisableBypass.IsChecked = config.ProxyRuleMode == ProxyRuleMode.Disable;
            ruleBypassLan.IsChecked = config.ProxyRuleMode == ProxyRuleMode.BypassLan;
            ruleBypassChina.IsChecked = config.ProxyRuleMode == ProxyRuleMode.BypassLanAndChina;
            ruleBypassNotChina.IsChecked = config.ProxyRuleMode == ProxyRuleMode.BypassLanAndNotChina;
            ruleUser.IsChecked = config.ProxyRuleMode == ProxyRuleMode.UserCustom;
        }

        private void LoadCurrentConfiguration()
        {
            var config = Global.GuiConfig;
            UpdateServersMenu();
            UpdateSysProxyMode(config);

            UpdateProxyRule(config);

            SelectRandomItem.IsChecked = config.Random;
            sameHostForSameTargetItem.IsChecked = config.SameHostForSameTarget;
            AutoCheckUpdateItem.IsChecked = config.AutoCheckUpdate;
            AllowPreReleaseItem.IsChecked = config.IsPreRelease;
        }

        private static Grid CreateSelectedIcon()
        {
            var icon = new Grid();
            icon.Children.Add(new Ellipse
            {
                Width = 8,
                Height = 8,
                Fill = Brushes.Black
            });
            return icon;
        }

        private void UpdateServersMenu()
        {
            var items = ServersItem.Items;
            while (!Equals(items[0], SeparatorItem))
            {
                items.RemoveAt(0);
            }

            var configuration = Global.GuiConfig;
            for (var i = 0; i < configuration.Configs.Count;)
            {
                configuration.Configs[i].Index = ++i;
            }
            var sub = new List<MenuItem>();
            var subTags = new HashSet<string>(configuration.Configs.Select(server => server.SubTag));
            foreach (var subTag in subTags)
            {
                var isSelected = false;
                var subItem = new MenuItem
                {
                    Header = string.IsNullOrEmpty(subTag) ? I18NUtil.GetAppStringValue(@"EmptySubtag") : subTag
                };
                var servers = configuration.Configs.Where(server => server.SubTag == subTag).ToArray();
                var groups = new HashSet<string>(servers.Select(server => server.Group));
                foreach (var group in groups)
                {
                    var groupItem = new MenuItem
                    {
                        Header = string.IsNullOrEmpty(group) ? I18NUtil.GetAppStringValue(@"EmptyGroup") : group
                    };
                    var subServers = servers.Where(server => server.Group == group);
                    foreach (var server in subServers)
                    {
                        var item = new MenuItem
                        {
                            Header = server.FriendlyName,
                            Tag = server.Index - 1
                        };
                        item.Click += AServerItem_Click;
                        if (configuration.Index == Convert.ToInt32(item.Tag))
                        {
                            item.IsChecked = true;
                            isSelected = true;
                        }
                        groupItem.Items.Add(item);
                    }
                    if (groups.Count > 1)
                    {
                        subItem.Items.Add(groupItem);
                        if (isSelected)
                        {
                            groupItem.Icon = CreateSelectedIcon();
                            subItem.Icon = CreateSelectedIcon();
                            isSelected = false;
                        }
                    }
                    else
                    {
                        groupItem.Header = subItem.Header;
                        sub.Add(groupItem);
                        if (isSelected)
                        {
                            groupItem.Icon = CreateSelectedIcon();
                        }
                    }
                }
                if (groups.Count > 1)
                {
                    sub.Add(subItem);
                }
            }
            var index = 0;
            foreach (var menuItem in sub)
            {
                items.Insert(index++, menuItem);
            }
        }

        private void ShowConfigForm(bool addNode)
        {
            if (_serverConfigWindow != null)
            {
                _serverConfigWindow.Activate();
                _serverConfigWindow.UpdateLayout();
                if (_serverConfigWindow.WindowState == WindowState.Minimized)
                {
                    _serverConfigWindow.WindowState = WindowState.Normal;
                }
                if (addNode)
                {
                    var cfg = Global.GuiConfig;
                    _serverConfigWindow.MoveToSelectedItem(cfg.Index + 1);
                }
            }
            else
            {
                configFrom_open = true;
                _serverConfigWindow = new ServerConfigWindow(controller, addNode ? -1 : -2);
                _serverConfigWindow.Show();
                _serverConfigWindow.Activate();
                _serverConfigWindow.BringToFront();
                _serverConfigWindow.Closed += ServerConfigWindowClosed;
            }
        }

        private void ServerConfigWindowClosed(object sender, EventArgs e)
        {
            _serverConfigWindow = null;
            configFrom_open = false;
            if (eventList.Count > 0)
            {
                foreach (var p in eventList)
                {
                    UpdateNodeCheckerNewNodeFound(p.sender, p.e);
                }

                eventList.Clear();
            }
        }

        private void ShowConfigForm(int index)
        {
            if (_serverConfigWindow != null)
            {
                _serverConfigWindow.Activate();
                _serverConfigWindow.UpdateLayout();
                if (_serverConfigWindow.WindowState == WindowState.Minimized)
                {
                    _serverConfigWindow.WindowState = WindowState.Normal;
                }
                _serverConfigWindow.Topmost = true;
                _serverConfigWindow.MoveToSelectedItem(index);
            }
            else
            {
                configFrom_open = true;
                _serverConfigWindow = new ServerConfigWindow(controller, index);
                _serverConfigWindow.Show();
                _serverConfigWindow.Activate();
                _serverConfigWindow.Topmost = true;
                _serverConfigWindow.Closed += ServerConfigWindowClosed;
            }
        }

        private void ShowSettingForm()
        {
            if (_settingsWindow != null)
            {
                _settingsWindow.Activate();
            }
            else
            {
                _settingsWindow = new SettingsWindow(controller);
                _settingsWindow.Show();
                _settingsWindow.Activate();
                _settingsWindow.BringToFront();
                _settingsWindow.Closed += (_, _) =>
                {
                    _settingsWindow = null;
                };
            }
        }

        private void ShowDnsSettingWindow()
        {
            if (_dnsSettingsWindow != null)
            {
                _dnsSettingsWindow.Activate();
            }
            else
            {
                _dnsSettingsWindow = new DnsSettingWindow();
                _dnsSettingsWindow.Show();
                _dnsSettingsWindow.Activate();
                _dnsSettingsWindow.BringToFront();
                _dnsSettingsWindow.Closed += (o, args) =>
                {
                    _dnsSettingsWindow = null;
                };
            }
        }

        private void ShowPortMapForm()
        {
            if (_portMapWindow != null)
            {
                _portMapWindow.Activate();
                _portMapWindow.UpdateLayout();
                if (_portMapWindow.WindowState == WindowState.Minimized)
                {
                    _portMapWindow.WindowState = WindowState.Normal;
                }
            }
            else
            {
                _portMapWindow = new PortSettingsWindow(controller);
                _portMapWindow.Show();
                _portMapWindow.Activate();
                _portMapWindow.BringToFront();
                _portMapWindow.Closed += (o, e) =>
                {
                    _portMapWindow = null;
                };
            }
        }

        private void ShowServerLogForm()
        {
            if (_serverLogWindow != null)
            {
                _serverLogWindow.Activate();
                _serverLogWindow.UpdateLayout();
                if (_serverLogWindow.WindowState == WindowState.Minimized)
                {
                    _serverLogWindow.WindowState = WindowState.Normal;
                }
            }
            else
            {
                _serverLogWindow = new ServerLogWindow(controller, _serverLogWindowStatus);
                _serverLogWindow.Show();
                _serverLogWindow.Activate();
                _serverLogWindow.BringToFront();
                _serverLogWindow.Closed += (o, e) =>
                {
                    _serverLogWindowStatus = new WindowStatus(_serverLogWindow);
                    _serverLogWindow = null;
                };
            }
        }

        private void ShowGlobalLogWindow()
        {
            if (_logWindow != null)
            {
                _logWindow.Activate();
                _logWindow.UpdateLayout();
                if (_logWindow.WindowState == WindowState.Minimized)
                {
                    _logWindow.WindowState = WindowState.Normal;
                }
            }
            else
            {
                _logWindow = new LogWindow();
                _logWindow.Show();
                _logWindow.Activate();
                _logWindow.BringToFront();
                _logWindow.Closed += (sender, args) =>
                {
                    _logWindow = null;
                };
            }
        }

        private void ShowSubscribeSettingForm()
        {
            if (_subScribeWindow != null)
            {
                _subScribeWindow.Activate();
                _subScribeWindow.UpdateLayout();
                if (_subScribeWindow.WindowState == WindowState.Minimized)
                {
                    _subScribeWindow.WindowState = WindowState.Normal;
                }
            }
            else
            {
                _subScribeWindow = new SubscribeWindow(controller);
                _subScribeWindow.Show();
                _subScribeWindow.Activate();
                _subScribeWindow.BringToFront();
                _subScribeWindow.Closed += (sender, args) =>
                {
                    _subScribeWindow = null;
                };
            }
        }

        private void Config_Click(object sender, EventArgs e)
        {
            if (sender is int i)
            {
                ShowConfigForm(i);
            }
            else
            {
                ShowConfigForm(false);
            }
        }

        private void Controller_ShowSubscribeWindowEvent(object sender, EventArgs e)
        {
            ShowSubscribeSettingForm();
        }

        private void Import_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() =>
            {
                var dlg = new OpenFileDialog
                {
                    InitialDirectory = Directory.GetCurrentDirectory()
                };
                if (dlg.ShowDialog() == true)
                {
                    var name = dlg.FileName;
                    var cfg = Global.LoadFile(name);
                    if (cfg.IsDefaultConfig())
                    {
                        MessageBox.Show(I18NUtil.GetAppStringValue(@"ImportConfigFailed"), HttpRequest.UpdateChecker.Name);
                    }
                    else
                    {
                        controller.MergeConfiguration(cfg);
                    }
                }
            });
        }

        private void Setting_Click(object sender, RoutedEventArgs e)
        {
            ShowSettingForm();
        }

        private void DnsSetting_Click(object sender, RoutedEventArgs e)
        {
            ShowDnsSettingWindow();
        }

        public void Quit_Click(object sender, EventArgs e)
        {
            controller.Stop();
            if (_serverConfigWindow != null)
            {
                _serverConfigWindow.Close();
                _serverConfigWindow = null;
            }
            if (_serverLogWindow != null)
            {
                _serverLogWindow.Close();
                _serverLogWindow = null;
            }
            if (timerDelayCheckUpdate != null)
            {
                timerDelayCheckUpdate.Elapsed -= timer_Elapsed;
                timerDelayCheckUpdate.Stop();
                timerDelayCheckUpdate = null;
            }
            if (_notifyIcon.Icon != null)
            {
                ViewUtils.DestroyIcon(_notifyIcon.Icon.Handle);
            }
            _notifyIcon.Dispose();
            Application.Current.Shutdown();
        }

        private static void OpenWiki_Click(object sender, RoutedEventArgs e)
        {
            Utils.OpenURL(@"https://github.com/HMBSbige/ShadowsocksR-Windows/wiki");
        }

        private static void FeedbackItem_Click(object sender, RoutedEventArgs e)
        {
            Utils.OpenURL(@"https://github.com/HMBSbige/ShadowsocksR-Windows/issues/new/choose");
        }

        private void notifyIcon_TrayLeftMouseUp(object sender, RoutedEventArgs e)
        {
            var key = Keyboard.IsKeyDown(Key.LeftShift) ? 1 : 0;
            key |= Keyboard.IsKeyDown(Key.RightShift) ? 1 : 0;
            key |= Keyboard.IsKeyDown(Key.LeftCtrl) ? 2 : 0;
            key |= Keyboard.IsKeyDown(Key.RightCtrl) ? 2 : 0;
            key |= Keyboard.IsKeyDown(Key.LeftAlt) ? 4 : 0;
            switch (key)
            {
                case 1:
                    ShowSettingForm();
                    break;
                case 2:
                    ShowServerLogForm();
                    break;
                case 3:
                    ShowSubscribeSettingForm();
                    break;
                case 4:
                    ShowPortMapForm();
                    break;
                case 6:
                    ShowDnsSettingWindow();
                    break;
                default:
                    ShowConfigForm(false);
                    break;
            }
        }

        private void notifyIcon_TrayMiddleMouseUp(object sender, RoutedEventArgs e)
        {
            ShowServerLogForm();
        }

        private void NoModifyItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.ToggleMode(ProxyMode.NoModify); });
        }

        private void EnableItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.ToggleMode(ProxyMode.Direct); });
        }

        private void GlobalModeItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.ToggleMode(ProxyMode.Global); });
        }

        private void PACModeItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.ToggleMode(ProxyMode.Pac); });
        }

        private void RuleBypassLanItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.ToggleRuleMode(ProxyRuleMode.BypassLan); });
        }

        private void RuleBypassChinaItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.ToggleRuleMode(ProxyRuleMode.BypassLanAndChina); });
        }

        private void RuleBypassNotChinaItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.ToggleRuleMode(ProxyRuleMode.BypassLanAndNotChina); });
        }

        private void RuleUserItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.ToggleRuleMode(ProxyRuleMode.UserCustom); });
        }

        private void RuleBypassDisableItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.ToggleRuleMode(ProxyRuleMode.Disable); });
        }

        private void SelectRandomItem_Click(object sender, RoutedEventArgs e)
        {
            SelectRandomItem.IsChecked = !SelectRandomItem.IsChecked;
            if (SelectRandomItem.IsChecked)
            {
                Task.Run(() => { controller.ToggleSelectRandom(true); });
            }
            else
            {
                Task.Run(() => { controller.ToggleSelectRandom(false); });
            }
        }

        private void AutoCheckUpdateItem_Click(object sender, RoutedEventArgs e)
        {
            AutoCheckUpdateItem.IsChecked = !AutoCheckUpdateItem.IsChecked;
            controller.ToggleSelectAutoCheckUpdate(AutoCheckUpdateItem.IsChecked);
        }

        private void AllowPreRelease_Click(object sender, RoutedEventArgs e)
        {
            AllowPreReleaseItem.IsChecked = !AllowPreReleaseItem.IsChecked;
            controller.ToggleSelectAllowPreRelease(AllowPreReleaseItem.IsChecked);
        }

        private void SelectSameHostForSameTargetItem_Click(object sender, RoutedEventArgs e)
        {
            sameHostForSameTargetItem.IsChecked = !sameHostForSameTargetItem.IsChecked;
            if (sameHostForSameTargetItem.IsChecked)
            {
                Task.Run(() => { controller.ToggleSameHostForSameTargetRandom(true); });
            }
            else
            {
                Task.Run(() => { controller.ToggleSameHostForSameTargetRandom(false); });
            }
        }

        private void CopyPacUrlItem_Click(object sender, RoutedEventArgs e)
        {
            controller.CopyPacUrl();
        }

        private void EditPACFileItem_Click(object sender, RoutedEventArgs e)
        {
            controller.TouchPACFile();
        }

        private void UpdatePACFromGFWListItem_Click(object sender, RoutedEventArgs e)
        {
            controller.UpdatePACFromGFWList();
        }

        private void UpdatePACFromLanIPListItem_Click(object sender, RoutedEventArgs e)
        {
            controller.UpdatePACFromOnlinePac(@"https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_lanip.pac");
        }

        private void UpdatePACFromCNWhiteListItem_Click(object sender, RoutedEventArgs e)
        {
            //域名白名单
            controller.UpdatePACFromOnlinePac(@"https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_white.pac");
        }

        private void UpdatePACFromCNOnlyListItem_Click(object sender, RoutedEventArgs e)
        {
            //回国
            controller.UpdatePACFromOnlinePac(@"https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_white_r.pac");
        }

        private void UpdatePACFromCnWhiteListIpItem_Click(object sender, RoutedEventArgs e)
        {
            //域名白名单+国内IP
            controller.UpdatePACFromOnlinePac(@"https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_cnall.pac");
        }

        private void UpdatePACFromChnIpItem_Click(object sender, RoutedEventArgs e)
        {
            //国内IP
            controller.UpdatePACFromOnlinePac(@"https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_cnip.pac");
        }

        private void EditUserRuleFileForGFWListItem_Click(object sender, RoutedEventArgs e)
        {
            controller.TouchUserRuleFile();
        }

        private void AServerItem_Click(object sender, EventArgs e)
        {
            var item = (MenuItem)sender;
            var index = (int)item.Tag;
            Task.Run(() =>
            {
                controller.DisconnectAllConnections(true);
                controller.SelectServerIndex(index);
            });
        }

        private void CheckUpdate_Click(object sender, RoutedEventArgs e)
        {
            updateChecker.Check(Global.GuiConfig, true);
        }

        private void CheckNodeUpdate_Click(object sender, RoutedEventArgs e)
        {
            Global.UpdateSubscribeManager.CreateTask(Global.GuiConfig, Global.UpdateNodeChecker, true);
        }

        private void ShowLogItem_Click(object sender, RoutedEventArgs e)
        {
            ShowGlobalLogWindow();
        }

        private void ShowPortMapItem_Click(object sender, RoutedEventArgs e)
        {
            ShowPortMapForm();
        }

        private void ShowServerLogItem_Click(object sender, RoutedEventArgs e)
        {
            ShowServerLogForm();
        }

        private void SubscribeSetting_Click(object sender, RoutedEventArgs e)
        {
            ShowSubscribeSettingForm();
        }

        private void DisconnectCurrent_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() => { controller.DisconnectAllConnections(); });
        }

        public void ImportAddress(string text)
        {
            ImportSsrUrl(text);

            ImportSubUrl(text);
        }

        private void ImportSsrUrl(string text)
        {
            if (controller.AddServerBySsUrl(text))
            {
                ShowConfigForm(true);
            }
        }

        private void ImportSubUrl(string text)
        {
            if (controller.AddSubscribeUrl(text))
            {
                ShowSubscribeSettingForm();
            }
        }

        private void ImportAddressFromClipboard_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var iData = Clipboard.GetDataObject();
                if (iData != null && iData.GetDataPresent(DataFormats.Text))
                {
                    ImportAddress((string)iData.GetData(DataFormats.Text));
                }
            }
            catch
            {
                // ignored
            }
        }

        #region QRCode

        private void ScanQRCodeItem_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(() =>
            {
                var w = (int)SystemParameters.VirtualScreenWidth;
                var h = (int)SystemParameters.VirtualScreenHeight;
                var x = (int)SystemParameters.VirtualScreenLeft;
                var y = (int)SystemParameters.VirtualScreenTop;
                var fullImage = new Bitmap(w, h);
                using (var g = Graphics.FromImage(fullImage))
                {
                    g.CopyFromScreen(x, y,
                            0, 0,
                            fullImage.Size,
                            CopyPixelOperation.SourceCopy);
                }

                const int maxTry = 10;
                for (var i = 0; i < maxTry; i++)
                {
                    var marginLeft = (int)((double)fullImage.Width * i / 2.5 / maxTry);
                    var marginTop = (int)((double)fullImage.Height * i / 2.5 / maxTry);
                    var cropRect = new Rectangle(marginLeft, marginTop, fullImage.Width - marginLeft * 2,
                            fullImage.Height - marginTop * 2);
                    var target = new Bitmap(w, h);

                    var imageScale = w / (double)cropRect.Width;
                    using (var g = Graphics.FromImage(target))
                    {
                        g.DrawImage(fullImage,
                        new Rectangle(0, 0, target.Width, target.Height),
                                cropRect,
                                GraphicsUnit.Pixel);
                    }

                    var result = QrCodeUtils.ScanBitmap(target);
                    if (result != null)
                    {
                        var success = controller.AddServerBySsUrl(result.Text);
                        var successSub = controller.AddSubscribeUrl(result.Text);
                        Application.Current.Dispatcher?.InvokeAsync(() =>
                        {
                            var splash = new QRCodeSplashWindow();
                            if (successSub)
                            {
                                splash.Closed += Splash_Closed0;
                            }
                            if (success)
                            {
                                splash.Closed += Splash_Closed;
                            }
                            if (!(successSub || success))
                            {
                                _urlToOpen = result.Text;
                                splash.Closed += Splash_Closed2;
                            }

                            double minX = int.MaxValue, minY = int.MaxValue, maxX = 0, maxY = 0;
                            foreach (var point in result.ResultPoints)
                            {
                                minX = Math.Min(minX, point.X);
                                minY = Math.Min(minY, point.Y);
                                maxX = Math.Max(maxX, point.X);
                                maxY = Math.Max(maxY, point.Y);
                            }

                            minX /= imageScale;
                            minY /= imageScale;
                            maxX /= imageScale;
                            maxY /= imageScale;
                            // make it 20% larger
                            var margin = (maxX - minX) * 0.20f;
                            minX += -margin + marginLeft;
                            maxX += margin + marginLeft;
                            minY += -margin + marginTop;
                            maxY += margin + marginTop;
                            splash.Left = x;
                            splash.Top = y;
                            splash.TargetRect = new Rectangle((int)minX, (int)minY, (int)maxX - (int)minX,
                                    (int)maxY - (int)minY);
                            splash.Width = fullImage.Width;
                            splash.Height = fullImage.Height;
                            fullImage.Dispose();
                            splash.Show();
                        });
                        return;
                    }
                }

                MessageBox.Show(I18NUtil.GetAppStringValue(@"QrCodeNotFound"));
            });
        }

        private void Splash_Closed(object sender, EventArgs e)
        {
            ShowConfigForm(true);
        }

        private void Splash_Closed0(object sender, EventArgs e)
        {
            ShowSubscribeSettingForm();
        }

        private void ShowUrlFromQrCode()
        {
            var dlg = new ShowTextWindow(_urlToOpen);
            dlg.Show();
            dlg.Activate();
            dlg.BringToFront();
        }

        private void Splash_Closed2(object sender, EventArgs e)
        {
            ShowUrlFromQrCode();
        }

        private void ShowUrlFromQrCode(object sender, RoutedEventArgs e)
        {
            ShowUrlFromQrCode();
        }

        #endregion
    }
}


================================================
FILE: shadowsocks-csharp/Controller/Service/HostDaemon.cs
================================================
using Shadowsocks.Model;
using System;
using System.IO;
using System.Threading.Tasks;

namespace Shadowsocks.Controller.Service
{
    public class HostDaemon
    {
        private FileSystemWatcher _userRuleWatcher;
        private FileSystemWatcher _chnIpWatcher;

        public event EventHandler UserRuleChanged;
        public event EventHandler ChnIpChanged;

        public HostDaemon()
        {
            WatchChnIp();
            WatchUserRule();
        }

        private void WatchChnIp()
        {
            _chnIpWatcher?.Dispose();
            _chnIpWatcher = new FileSystemWatcher(Directory.GetCurrentDirectory())
            {
                NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName,
                Filter = IPRangeSet.ChnFilename
            };
            _chnIpWatcher.Changed += ChnIpWatcher_Changed;
            _chnIpWatcher.Created += ChnIpWatcher_Changed;
            _chnIpWatcher.Deleted += ChnIpWatcher_Changed;
            _chnIpWatcher.Renamed += ChnIpWatcher_Changed;
            _chnIpWatcher.EnableRaisingEvents = true;
        }

        private void WatchUserRule()
        {
            _userRuleWatcher?.Dispose();
            _userRuleWatcher = new FileSystemWatcher(Directory.GetCurrentDirectory())
            {
                NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName,
                Filter = HostMap.UserRule
            };
            _userRuleWatcher.Changed += UserRuleWatcher_Changed;
            _userRuleWatcher.Created += UserRuleWatcher_Changed;
            _userRuleWatcher.Deleted += UserRuleWatcher_Changed;
            _userRuleWatcher.Renamed += UserRuleWatcher_Changed;
            _userRuleWatcher.EnableRaisingEvents = true;
        }

        private void UserRuleWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            if (UserRuleChanged == null)
            {
                return;
            }

            try
            {
                ((FileSystemWatcher)sender).EnableRaisingEvents = false;
                Logging.Info($@"Detected: user rule file '{e.Name}' was {e.ChangeType.ToString().ToLower()}.");
                Task.Delay(10).ContinueWith(task => UserRuleChanged(this, EventArgs.Empty));
            }
            finally
            {
                ((FileSystemWatcher)sender).EnableRaisingEvents = true;
            }
        }

        private void ChnIpWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            if (ChnIpChanged == null)
            {
                return;
            }

            try
            {
                ((FileSystemWatcher)sender).EnableRaisingEvents = false;
                Logging.Info($@"Detected: '{e.Name}' was {e.ChangeType.ToString().ToLower()}.");
                Task.Delay(10).ContinueWith(task => ChnIpChanged(this, EventArgs.Empty));
            }
            finally
            {
                ((FileSystemWatcher)sender).EnableRaisingEvents = true;
            }
        }
    }
}


================================================
FILE: shadowsocks-csharp/Controller/Service/HostMap.cs
================================================
using Shadowsocks.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;

namespace Shadowsocks.Controller.Service
{
    public static class HostMap
    {
        private static readonly Dictionary<string, HostNode> Root = new();
        private static IPSegment _ips;

        public const string UserRule = @"user.rule";

        static HostMap()
        {
            Clear();
        }

        private static void Clear()
        {
            Root.Clear();
            _ips = new IPSegment(@"remoteproxy");
        }

        public static void Reload()
        {
            Clear();
            LoadHostFile();
        }

        private static void AddHost(string host, string addr)
        {
            if (IPAddress.TryParse(host, out _))
            {
                var addr_parts = addr.Split(new[] { ' ', '\t' }, 2, StringSplitOptions.RemoveEmptyEntries);
                if (addr_parts.Length >= 2)
                {
                    _ips.insert(new IPAddressCmp(host), new IPAddressCmp(addr_parts[0]), addr_parts[1]);
                    return;
                }
            }

            var parts = host.Split('.');
            var node = Root;
            var include_sub = false;
            var end = 0;
            if (parts[0].Length == 0)
            {
                end = 1;
                include_sub = true;
            }
            for (var i = parts.Length - 1; i > end; --i)
            {
                if (!node.ContainsKey(parts[i]))
                {
                    node[parts[i]] = new HostNode();
                }
                if (node[parts[i]].SubNode == null)
                {
                    node[parts[i]].SubNode = new Dictionary<string, HostNode>();
                }
                node = node[parts[i]].SubNode;
            }
            node[parts[end]] = new HostNode(include_sub, addr);
        }

        public static bool GetHost(string host, out string addr)
        {
            var parts = host.Split('.');
            var node = Root;
            addr = null;
            for (var i = parts.Length - 1; i >= 0; --i)
            {
                if (!node.ContainsKey(parts[i]))
                {
                    return false;
                }
                if (node[parts[i]].Addr.Length > 0 || node[parts[i]].IncludeSub)
                {
                    addr = node[parts[i]].Addr;
                    return true;
                }
                if (node.ContainsKey("*"))
                {
                    addr = node["*"].Addr;
                    return true;
                }
                if (node[parts[i]].SubNode == null)
                {
                    return false;
                }
                node = node[parts[i]].SubNode;
            }
            return false;
        }

        public static bool GetIP(IPAddress ip, out string addr)
        {
            var host = ip.ToString();
            addr = _ips.Get(new IPAddressCmp(host)) as string;
            return addr != null;
        }

        private static void LoadHostFile()
        {
            if (File.Exists(UserRule))
            {
                try
                {
                    foreach (var line in File.ReadLines(UserRule))
                    {
                        if (line.Length > 0 && line.StartsWith(@"#"))
                        {
                            continue;
                        }

                        var parts = line.Split(new[] { ' ', '\t' }, 2, StringSplitOptions.RemoveEmptyEntries);
                        if (parts.Length < 2)
                        {
                            continue;
                        }

                        AddHost(parts[0], parts[1]);
                    }
                }
                catch
                {
                    // ignored
                }
            }
        }
    }
}


================================================
FILE: shadowsocks-csharp/Controller/Service/HttpPortForwarder.cs
================================================
using Shadowsocks.Model;
using Shadowsocks.Proxy;
using Shadowsocks.Util.NetUtils;
using System;
using System.Net;
using System.Net.Sockets;

namespace Shadowsocks.Controller.Service
{
    internal class HttpPortForwarder : Listener.Service
    {
        private readonly int _targetPort;
        private readonly Configuration _config;

        public HttpPortForwarder(int targetPort, Configuration config)
        {
            _targetPort = targetPort;
            _config = config;
        }

        public override bool Handle(byte[] firstPacket, int length, Socket socket)
        {
            if (socket.ProtocolType != ProtocolType.Tcp)
            {
                return false;
            }
            new Handler().Start(_config, firstPacket, length, socket, _targetPort);
            return true;
        }

        private class Handler
        {
            private byte[] _firstPacket;
            private int _firstPacketLength;
            private int _targetPort;
            private Socket _local;
            private WrappedSocket _remote;
            private bool _closed;
            private bool _localShutdown;
            private bool _remoteShutdown;
            private Configuration _config;

            private HttpParser _httpProxyState;

            private const int RecvSize = 4096;
            // remote receive buffer
            private readonly byte[] _remoteRecvBuffer = new byte[RecvSize];
            // connection receive buffer
            private readonly byte[] _connetionRecvBuffer = new byte[RecvSize];

            public void Start(Configuration config, byte[] firstPacket, int length, Socket socket, int targetPort)
            {
                _config = config;
                _firstPacket = firstPacket;
                _firstPacketLength = length;
                _local = socket;
                _targetPort = targetPort;
                if ((_config.AuthUser ?? string.Empty).Length == 0
                || IPSubnet.IsLoopBack(((IPEndPoint)_local.RemoteEndPoint).Address))
                {
                    Connect();
                }
                else
                {
                    RspHttpHandshakeReceive();
                }
            }

            private void RspHttpHandshakeReceive()
            {
                if (_httpProxyState == null)
                {
                    _httpProxyState = new HttpParser(true);
                }
                _httpProxyState.httpAuthUser = _config.AuthUser;
                _httpProxyState.httpAuthPass = _config.AuthPass;
                var err = _httpProxyState.HandshakeReceive(_firstPacket, _firstPacketLength, out _);
                if (err == 1)
                {
                    _local.BeginReceive(_connetionRecvBuffer, 0, _firstPacket.Length, 0,
                        HttpHandshakeRecv, null);
                }
                else if (err == 2)
                {
                    var dataSend = HttpParser.Http407();
                    var httpData = System.Text.Encoding.UTF8.GetBytes(dataSend);
                    _local.BeginSend(httpData, 0, httpData.Length, 0, HttpHandshakeAuthEndSend, null);
                }
                else if (err == 3)
                {
                    Connect();
                }
                else if (err == 4)
                {
                    Connect();
                }
                else if (err == 0)
                {
                    var dataSend = HttpParser.Http200();
                    var httpData = System.Text.Encoding.UTF8.GetBytes(dataSend);
                    _local.BeginSend(httpData, 0, httpData.Length, 0, StartConnect, null);
                }
                else if (err == 500)
                {
                    var dataSend = HttpParser.Http500();
                    var httpData = System.Text.Encoding.UTF8.GetBytes(dataSend);
                    _local.BeginSend(httpData, 0, httpData.Length, 0, HttpHandshakeAuthEndSend, null);
                }
            }

            private void HttpHandshakeRecv(IAsyncResult ar)
            {
                if (_closed)
                {
                    return;
                }
                try
                {
                    var bytesRead = _local.EndReceive(ar);
                    if (bytesRead > 0)
                    {
                        Array.Copy(_connetionRecvBuffer, _firstPacket, bytesRead);
                        _firstPacketLength = bytesRead;
                        RspHttpHandshakeReceive();
                    }
                    else
                    {
                        Console.WriteLine(@"failed to recv data in HttpHandshakeRecv");
                        Close();
                    }
                }
                catch (Exception e)
                {
                    Logging.LogUsefulException(e);
                    Close();
                }
            }

            private void HttpHandshakeAuthEndSend(IAsyncResult ar)
            {
                if (_closed)
                {
                    return;
                }
                try
                {
                    _local.EndSend(ar);
                    _local.BeginReceive(_connetionRecvBuffer, 0, _firstPacket.Length, 0,
                        HttpHandshakeRecv, null);
                }
                catch (Exception e)
                {
                    Logging.LogUsefulException(e);
                    Close();
                }
            }

            private void StartConnect(IAsyncResult ar)
            {
                try
                {
                    _local.EndSend(ar);
                    Connect();
                }
                catch (Exception e)
                {
                    Logging.LogUsefulException(e);
                    Close();
                }

            }

            private void Connect()
            {
                try
                {
                    var ipAddress = Global.OSSupportsLocalIPv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback;
                    var remoteEp = new IPEndPoint(ipAddress, _targetPort);

                    _remote = new WrappedSocket();

                    // Connect to the remote endpoint.
                    _remote.BeginConnect(remoteEp, ConnectCallback, null);
                }
                catch (Exception e)
                {
                    Logging.LogUsefulException(e);
                    Close();
                }
            }

            private void ConnectCallback(IAsyncResult ar)
            {
                if (_closed)
                {
                    return;
                }
                try
                {
                    _remote.EndConnect(ar);
                    _remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
                    HandshakeReceive();
                }
                catch (Exception e)
                {
                    Logging.LogUsefulException(e);
                    Close();
                }
            }

            private void Handshake
Download .txt
gitextract_jyjjkvlh/

├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   ├── feature_request.md
│   │   └── other-issue.md
│   ├── renovate.json
│   └── workflows/
│       └── CI.yml
├── .gitignore
├── Build/
│   └── DotNetDllPathPatcher.ps1
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── UnitTest/
│   ├── DnsTest.cs
│   ├── EncryptionTest.cs
│   ├── IPSubnet.cs
│   ├── ServerTest.cs
│   ├── SubscribeTest.cs
│   ├── UnitTest.cs
│   └── UnitTest.csproj
├── build.ps1
├── shadowsocks-csharp/
│   ├── Controller/
│   │   ├── AutoStartup.cs
│   │   ├── FileManager.cs
│   │   ├── HttpRequest/
│   │   │   ├── GfwListUpdater.cs
│   │   │   ├── HttpRequest.cs
│   │   │   ├── UpdateChecker.cs
│   │   │   └── UpdateNode.cs
│   │   ├── Logging.cs
│   │   ├── MainController.cs
│   │   ├── MenuViewController.cs
│   │   ├── Service/
│   │   │   ├── HostDaemon.cs
│   │   │   ├── HostMap.cs
│   │   │   ├── HttpPortForwarder.cs
│   │   │   ├── HttpProxyRunner.cs
│   │   │   ├── Listener.cs
│   │   │   ├── Local.cs
│   │   │   ├── PACDaemon.cs
│   │   │   ├── PACServer.cs
│   │   │   ├── ProtocolResponseDetector.cs
│   │   │   ├── Socks5Forwarder.cs
│   │   │   ├── SpeedTest.cs
│   │   │   └── UpdateSubscribeManager.cs
│   │   └── SystemProxy.cs
│   ├── Data/
│   │   ├── abp.js
│   │   ├── chn_ip.txt
│   │   ├── proxy.pac.txt
│   │   └── user-rule.txt
│   ├── Encryption/
│   │   ├── CircularBuffer/
│   │   │   └── ByteCircularBuffer.cs
│   │   ├── CryptoUtils.cs
│   │   ├── EncryptorBase.cs
│   │   ├── EncryptorFactory.cs
│   │   ├── EncryptorInfo.cs
│   │   ├── Exception/
│   │   │   └── CryptoException.cs
│   │   ├── IEncryptor.cs
│   │   ├── OpenSSL.cs
│   │   ├── Sodium.cs
│   │   └── Stream/
│   │       ├── NoneEncryptor.cs
│   │       ├── StreamEncryptor.cs
│   │       ├── StreamOpenSSLEncryptor.cs
│   │       └── StreamSodiumEncryptor.cs
│   ├── Enums/
│   │   ├── BalanceType.cs
│   │   ├── DnsType.cs
│   │   ├── HttpRequestProxyType.cs
│   │   ├── LogLevel.cs
│   │   ├── PacType.cs
│   │   ├── PortMapType.cs
│   │   ├── ProxyMode.cs
│   │   ├── ProxyRuleMode.cs
│   │   ├── ProxyType.cs
│   │   └── ServerTreeViewType.cs
│   ├── I18N/
│   │   ├── App.en-US.xaml
│   │   ├── App.zh-CN.xaml
│   │   ├── App.zh-TW.xaml
│   │   ├── ConfigWindow.en-US.xaml
│   │   ├── ConfigWindow.zh-CN.xaml
│   │   ├── ConfigWindow.zh-TW.xaml
│   │   ├── DnsSettingWindow.en-US.xaml
│   │   ├── DnsSettingWindow.zh-CN.xaml
│   │   ├── DnsSettingWindow.zh-TW.xaml
│   │   ├── LogWindow.en-US.xaml
│   │   ├── LogWindow.zh-CN.xaml
│   │   ├── LogWindow.zh-TW.xaml
│   │   ├── PortSettingsWindow.en-US.xaml
│   │   ├── PortSettingsWindow.zh-CN.xaml
│   │   ├── PortSettingsWindow.zh-TW.xaml
│   │   ├── ServerLogWindow.en-US.xaml
│   │   ├── ServerLogWindow.zh-CN.xaml
│   │   ├── ServerLogWindow.zh-TW.xaml
│   │   ├── SettingsWindow.en-US.xaml
│   │   ├── SettingsWindow.zh-CN.xaml
│   │   ├── SettingsWindow.zh-TW.xaml
│   │   ├── SubscribeWindow.en-US.xaml
│   │   ├── SubscribeWindow.zh-CN.xaml
│   │   └── SubscribeWindow.zh-TW.xaml
│   ├── Model/
│   │   ├── Configuration.cs
│   │   ├── ConfigurationException.cs
│   │   ├── Connections.cs
│   │   ├── DnsBuffer.cs
│   │   ├── DnsClient.cs
│   │   ├── ErrorLog.cs
│   │   ├── Global.cs
│   │   ├── HostNode.cs
│   │   ├── IPRangeSet.cs
│   │   ├── IPSegment.cs
│   │   ├── LRUCache.cs
│   │   ├── MinSearchTree.cs
│   │   ├── PortMapConfig.cs
│   │   ├── PortMapConfigCache.cs
│   │   ├── Rule.cs
│   │   ├── Server.cs
│   │   ├── ServerSelectStrategy.cs
│   │   ├── ServerSubscribe.cs
│   │   ├── ServerTreeViewModel.cs
│   │   ├── Transfer/
│   │   │   ├── ServerSpeedLog.cs
│   │   │   ├── ServerTrans.cs
│   │   │   ├── ServerTransferTotal.cs
│   │   │   └── TransLog.cs
│   │   ├── UriVisitTime.cs
│   │   └── WindowStatus.cs
│   ├── Obfs/
│   │   ├── AuthAES128SHA1.cs
│   │   ├── AuthAkarin.cs
│   │   ├── AuthAkarin_spec_a.cs
│   │   ├── AuthChain_a.cs
│   │   ├── AuthChain_b.cs
│   │   ├── AuthChain_c.cs
│   │   ├── AuthChain_d.cs
│   │   ├── AuthChain_e.cs
│   │   ├── AuthChain_f.cs
│   │   ├── AuthData.cs
│   │   ├── AuthSHA1.cs
│   │   ├── AuthSHA1V2.cs
│   │   ├── AuthSHA1V4.cs
│   │   ├── HttpSimpleObfs.cs
│   │   ├── IObfs.cs
│   │   ├── ObfsBase.cs
│   │   ├── ObfsException.cs
│   │   ├── ObfsFactory.cs
│   │   ├── Plain.cs
│   │   ├── ProtocolException.cs
│   │   ├── ServerInfo.cs
│   │   ├── TlsAuthData.cs
│   │   ├── TlsTicketAuthObfs.cs
│   │   ├── VerifyData.cs
│   │   ├── VerifyDeflateObfs.cs
│   │   ├── VerifySimpleBase.cs
│   │   └── xorshift128plus.cs
│   ├── Program.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── Proxy/
│   │   ├── CallbackState.cs
│   │   ├── CallbackStatus.cs
│   │   ├── Handler.cs
│   │   ├── HandlerConfig.cs
│   │   ├── HttpParser.cs
│   │   ├── IHandler.cs
│   │   ├── ProxyAuthHandler.cs
│   │   ├── ProxyEncryptSocket.cs
│   │   ├── ProxySocketTun.cs
│   │   └── ProxySocketTunLocal.cs
│   ├── SyncfusionLicenseRegister.bat
│   ├── Util/
│   │   ├── Base64.cs
│   │   ├── CRC.cs
│   │   ├── ColorConvert.cs
│   │   ├── Constants.cs
│   │   ├── I18NUtil.cs
│   │   ├── JsonUtils.cs
│   │   ├── NetUtils/
│   │   │   ├── DnsUtil.cs
│   │   │   ├── IPSubnet.cs
│   │   │   ├── SocketUtil.cs
│   │   │   └── WrappedSocket.cs
│   │   ├── QrCodeUtils.cs
│   │   ├── RNG.cs
│   │   ├── Reg.cs
│   │   ├── Utils.cs
│   │   └── ViewUtils.cs
│   ├── View/
│   │   ├── Controls/
│   │   │   ├── BindablePasswordBox.cs
│   │   │   ├── GridColumnSizerExt.cs
│   │   │   ├── MaskedTextBox.xaml
│   │   │   ├── MaskedTextBox.xaml.cs
│   │   │   ├── NumberUpDown.xaml
│   │   │   └── NumberUpDown.xaml.cs
│   │   ├── DnsSettingWindow.xaml
│   │   ├── DnsSettingWindow.xaml.cs
│   │   ├── LogWindow.xaml
│   │   ├── LogWindow.xaml.cs
│   │   ├── NotifyIconResources.xaml
│   │   ├── PortSettingsWindow.xaml
│   │   ├── PortSettingsWindow.xaml.cs
│   │   ├── QRCodeSplashWindow.xaml
│   │   ├── QRCodeSplashWindow.xaml.cs
│   │   ├── ServerConfigWindow.xaml
│   │   ├── ServerConfigWindow.xaml.cs
│   │   ├── ServerLogWindow.xaml
│   │   ├── ServerLogWindow.xaml.cs
│   │   ├── SettingsWindow.xaml
│   │   ├── SettingsWindow.xaml.cs
│   │   ├── ShowTextWindow.xaml
│   │   ├── ShowTextWindow.xaml.cs
│   │   ├── SubscribeWindow.xaml
│   │   ├── SubscribeWindow.xaml.cs
│   │   └── ValueConverter/
│   │       ├── BalanceTypeEnumConverter.cs
│   │       ├── BooleanToEnabledConverter.cs
│   │       ├── ConnectEmptyToBrushConverter.cs
│   │       ├── ConnectErrorToBrushConverter.cs
│   │       ├── ConnectNumberToBrushConverter.cs
│   │       ├── ErrorPercentToBrushConverter.cs
│   │       ├── LatencyToBrushConverter.cs
│   │       ├── ProxyTypeConverter.cs
│   │       ├── ProxyTypeEnumConverter.cs
│   │       ├── ServerTreeTypeToFontConverter.cs
│   │       ├── SpeedToBrushConverter.cs
│   │       ├── TotalDownloadBackgroundBrushConvert.cs
│   │       ├── TotalDownloadRawBackgroundBrushConvert.cs
│   │       ├── TotalUploadBackgroundBrushConvert.cs
│   │       └── UnixSecondsToString.cs
│   ├── ViewModel/
│   │   ├── DnsSettingViewModel.cs
│   │   ├── ServerConfigViewModel.cs
│   │   ├── ServerLogViewModel.cs
│   │   ├── SettingViewModel.cs
│   │   ├── SubscribeWindowViewModel.cs
│   │   └── ViewModelBase.cs
│   └── shadowsocksr.csproj
└── shadowsocks-csharp.sln
Download .txt
SYMBOL INDEX (1322 symbols across 165 files)

FILE: UnitTest/DnsTest.cs
  class DnsTest (line 12) | [TestClass]
    method DefaultTest (line 15) | [TestMethod]
    method Test (line 24) | [TestMethod]
    method DnsOverTlsTest (line 39) | [TestMethod]
    method TestTwoDnsAsync (line 48) | [TestMethod]
    method TestIpv6FallbackAsync (line 68) | [TestMethod]
    method TestIpv6FirstAsync (line 96) | [TestMethod]

FILE: UnitTest/EncryptionTest.cs
  class EncryptionTest (line 11) | [TestClass]
    method RunEncryptionRound (line 14) | private void RunEncryptionRound(IEncryptor encryptor, IEncryptor decry...
    method TestStreamOpenSSLEncryption (line 43) | [TestMethod]
    method RunSingleStreamOpenSSLEncryptionThread (line 78) | private void RunSingleStreamOpenSSLEncryptionThread(string methodName ...
    method TestStreamSodiumEncryption (line 88) | [TestMethod]
    method RunSingleStreamSodiumEncryptionThread (line 122) | private void RunSingleStreamSodiumEncryptionThread(string methodName =...

FILE: UnitTest/IPSubnet.cs
  class IPSubnetTest (line 7) | [TestClass]
    method IsLoopBackTest (line 10) | [TestMethod]
    method IsInSubnetTest (line 21) | [TestMethod]

FILE: UnitTest/ServerTest.cs
  class ServerTest (line 7) | [TestClass]
    method TestServerFromSSR (line 10) | [TestMethod]
    method TestBadPortNumber (line 44) | [TestMethod]

FILE: UnitTest/SubscribeTest.cs
  class SubscribeTest (line 9) | [TestClass]
    method ParseTest (line 12) | [TestMethod]

FILE: UnitTest/UnitTest.cs
  class UnitTest (line 10) | [TestClass]
    method TestMd5 (line 13) | [TestMethod]
    method EncryptStringTest (line 22) | [TestMethod]

FILE: shadowsocks-csharp/Controller/AutoStartup.cs
  class AutoStartup (line 9) | internal static class AutoStartup
    method Set (line 13) | public static bool Set(bool enabled)

FILE: shadowsocks-csharp/Controller/FileManager.cs
  class FileManager (line 10) | public static class FileManager
    method ByteArrayToFile (line 12) | public static bool ByteArrayToFile(string fileName, byte[] content)
    method DecompressFile (line 28) | public static void DecompressFile(string fileName, byte[] content)
    method DeflateCompress (line 51) | public static byte[] DeflateCompress(byte[] content, int index, int co...
    method DeflateDecompress (line 72) | public static byte[] DeflateDecompress(byte[] content, int index, int ...
    method ZipCompressToFile (line 100) | [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
    method NonExclusiveReadAllText (line 130) | public static string NonExclusiveReadAllText(string path)
    method NonExclusiveReadAllText (line 135) | public static string NonExclusiveReadAllText(string path, Encoding enc...

FILE: shadowsocks-csharp/Controller/HttpRequest/GfwListUpdater.cs
  class GfwListUpdater (line 14) | public class GfwListUpdater : HttpRequest
    class ResultEventArgs (line 24) | public class ResultEventArgs : EventArgs
      method ResultEventArgs (line 29) | public ResultEventArgs(bool success, PacType pacType)
    method UpdatePacFromGfwList (line 40) | public async void UpdatePacFromGfwList(Configuration config)
    method MergeAndWritePacFile (line 59) | public static bool MergeAndWritePacFile(string gfwListResult)
    method MergePacFile (line 75) | private static string MergePacFile(string gfwListResult)
    method ParseBase64ToValidList (line 93) | private static List<string> ParseBase64ToValidList(string response)
    method ParseToValidList (line 100) | private static List<string> ParseToValidList(string content)
    method UpdateOnlinePac (line 112) | public async void UpdateOnlinePac(Configuration config, string url)

FILE: shadowsocks-csharp/Controller/HttpRequest/HttpRequest.cs
  class HttpRequest (line 9) | public abstract class HttpRequest
    method CreateClient (line 15) | public static HttpClient CreateClient(bool useProxy, IWebProxy proxy, ...
    method GetAsync (line 33) | private static async Task<string> GetAsync(string url, IWebProxy proxy...
    method HeadAsync (line 41) | private static async Task<bool> HeadAsync(string url, IWebProxy proxy,...
    method AutoGetAsync (line 55) | protected static async Task<string> AutoGetAsync(string url, IWebProxy...
    method DirectGetAsync (line 78) | protected static async Task<string> DirectGetAsync(string url, string ...
    method ProxyGetAsync (line 84) | protected static async Task<string> ProxyGetAsync(string url, IWebProx...
    method DefaultGetAsync (line 90) | protected static async Task<string> DefaultGetAsync(string url, string...
    method CreateProxy (line 96) | protected static IWebProxy CreateProxy(Configuration config)

FILE: shadowsocks-csharp/Controller/HttpRequest/UpdateChecker.cs
  class UpdateChecker (line 7) | public class UpdateChecker : HttpRequest
    method Check (line 39) | public async void Check(Configuration config, bool notifyNoFound)

FILE: shadowsocks-csharp/Controller/HttpRequest/UpdateNode.cs
  class UpdateNode (line 8) | public class UpdateNode : HttpRequest
    method CheckUpdate (line 17) | public void CheckUpdate(Configuration config, ServerSubscribe subscrib...
    method Update (line 34) | private async void Update(HttpRequestProxyType proxyType, IWebProxy pr...

FILE: shadowsocks-csharp/Controller/Logging.cs
  class Logging (line 14) | public static class Logging
    method OpenLogFile (line 27) | public static bool OpenLogFile()
    method CloseLogFile (line 63) | private static void CloseLogFile()
    method Clear (line 74) | public static void Clear()
    method Error (line 84) | public static void Error(object o)
    method Info (line 90) | public static void Info(object o)
    method Debug (line 96) | [Conditional("DEBUG")]
    method ToString (line 103) | private static string ToString(IEnumerable<StackFrame> stacks)
    method CompressOldLogFile (line 108) | private static void CompressOldLogFile()
    method UpdateLogFile (line 126) | private static void UpdateLogFile()
    method LogUsefulException (line 140) | public static void LogUsefulException(Exception e)
    method LogSocketException (line 188) | public static bool LogSocketException(string remarks, string server, E...
    method Log (line 232) | public static void Log(LogLevel level, object s)
    method LogBin (line 238) | [Conditional("DEBUG")]
  class StreamWriterWithTimestamp (line 253) | public class StreamWriterWithTimestamp : StreamWriter
    method StreamWriterWithTimestamp (line 255) | public StreamWriterWithTimestamp(Stream stream) : base(stream)
    method GetTimestamp (line 259) | private static string GetTimestamp()
    method WriteLine (line 264) | public override void WriteLine(string value)
    method Write (line 276) | public override void Write(string value)

FILE: shadowsocks-csharp/Controller/MainController.cs
  class MainController (line 17) | public class MainController
    class PathEventArgs (line 36) | public class PathEventArgs : EventArgs
    method MainController (line 59) | public MainController()
    method ReportError (line 73) | private void ReportError(Exception e)
    method FindFirstMatchServer (line 78) | private static int FindFirstMatchServer(Server server, IReadOnlyList<S...
    method AppendConfiguration (line 90) | private static void AppendConfiguration(Configuration mergeConfig, IRe...
    method MergeConfiguration (line 107) | private static IEnumerable<Server> MergeConfiguration(Configuration me...
    method MergeGetConfiguration (line 126) | private static Configuration MergeGetConfiguration(Configuration merge...
    method MergeConfiguration (line 140) | public void MergeConfiguration(Configuration mergeConfig)
    method SaveServersConfig (line 146) | public void SaveServersConfig(Configuration config, bool reload)
    method SaveServersPortMap (line 165) | public void SaveServersPortMap(Configuration config)
    method SelectServerIndex (line 177) | public void SelectServerIndex(int index)
    method AddServerBySsUrl (line 186) | public bool AddServerBySsUrl(string ssUrLs, string force_group = null,...
    method AddSubscribeUrl (line 228) | public bool AddSubscribeUrl(string str)
    method ToggleMode (line 276) | public void ToggleMode(ProxyMode mode)
    method ToggleRuleMode (line 296) | public void ToggleRuleMode(ProxyRuleMode mode)
    method ToggleSelectRandom (line 302) | public void ToggleSelectRandom(bool enabled)
    method ToggleSameHostForSameTargetRandom (line 312) | public void ToggleSameHostForSameTargetRandom(bool enabled)
    method ToggleSelectAutoCheckUpdate (line 318) | public void ToggleSelectAutoCheckUpdate(bool enabled)
    method ToggleSelectAllowPreRelease (line 324) | public void ToggleSelectAllowPreRelease(bool enabled)
    method SaveAndNotifyChanged (line 333) | public void SaveAndNotifyChanged()
    method SaveAndReload (line 342) | private void SaveAndReload()
    method StopPortMap (line 348) | private void StopPortMap()
    method LoadPortMap (line 361) | private void LoadPortMap()
    method Stop (line 383) | public void Stop()
    method ClearTransferTotal (line 402) | public void ClearTransferTotal(string serverId)
    method TouchPACFile (line 409) | public void TouchPACFile()
    method TouchUserRuleFile (line 414) | public void TouchUserRuleFile()
    method UpdatePACFromGFWList (line 419) | public void UpdatePACFromGFWList()
    method UpdatePACFromOnlinePac (line 424) | public void UpdatePACFromOnlinePac(string url)
    method ReloadPacServer (line 429) | private void ReloadPacServer()
    method ReloadIPRange (line 450) | private void ReloadIPRange()
    method ReloadProxyRule (line 456) | private void ReloadProxyRule()
    method Reload (line 469) | public void Reload()
    method ThrowSocketException (line 519) | private static void ThrowSocketException(ref Exception e)
    method UpdateSystemProxy (line 544) | private void UpdateSystemProxy()
    method PacDaemon_UserRuleFileChanged (line 549) | private void PacDaemon_UserRuleFileChanged(object sender, EventArgs e)
    method ShowConfigForm (line 567) | public void ShowConfigForm(int? index = null)
    method ShowSubscribeWindow (line 572) | public void ShowSubscribeWindow()
    method DisconnectAllConnections (line 580) | public void DisconnectAllConnections(bool checkSwitchAutoCloseAll = fa...
    method CopyPacUrl (line 594) | public void CopyPacUrl()

FILE: shadowsocks-csharp/Controller/MenuViewController.cs
  class MenuViewController (line 25) | public class MenuViewController
    class EventParams (line 27) | private class EventParams
      method EventParams (line 32) | public EventParams(object sender, EventArgs e)
    method MenuViewController (line 89) | public MenuViewController(MainController controller)
    method timer_Elapsed (line 130) | private void timer_Elapsed(object sender, System.Timers.ElapsedEventAr...
    method ControllerError (line 143) | private static void ControllerError(object sender, ErrorEventArgs e)
    method UpdateTrayIcon (line 148) | private void UpdateTrayIcon()
    method LoadMenu (line 240) | private void LoadMenu()
    method controller_ConfigChanged (line 355) | private void controller_ConfigChanged(object sender, EventArgs e)
    method controller_FileReadyToOpen (line 361) | private void controller_FileReadyToOpen(object sender, MainController....
    method controller_UpdatePACFromGFWListError (line 366) | private void controller_UpdatePACFromGFWListError(object sender, Error...
    method controller_UpdatePACFromGFWListCompleted (line 372) | private void controller_UpdatePACFromGFWListCompleted(object sender, G...
    method UpdateNodeCheckerNewNodeFound (line 381) | private void UpdateNodeCheckerNewNodeFound(object sender, EventArgs e)
    method updateChecker_NewVersionFound (line 573) | private void updateChecker_NewVersionFound(object sender, EventArgs e)
    method updateChecker_NewVersionNotFound (line 595) | private void updateChecker_NewVersionNotFound(object sender, EventArgs e)
    method UpdateChecker_NewVersionFoundFailed (line 602) | private void UpdateChecker_NewVersionFoundFailed(object sender, EventA...
    method UpdateItem_Clicked (line 607) | private void UpdateItem_Clicked(object sender, RoutedEventArgs e)
    method notifyIcon_TrayBalloonTipClicked (line 616) | private void notifyIcon_TrayBalloonTipClicked(object sender, RoutedEve...
    method UpdateSysProxyMode (line 625) | private void UpdateSysProxyMode(Configuration config)
    method UpdateProxyRule (line 633) | private void UpdateProxyRule(Configuration config)
    method LoadCurrentConfiguration (line 642) | private void LoadCurrentConfiguration()
    method CreateSelectedIcon (line 656) | private static Grid CreateSelectedIcon()
    method UpdateServersMenu (line 668) | private void UpdateServersMenu()
    method ShowConfigForm (line 746) | private void ShowConfigForm(bool addNode)
    method ServerConfigWindowClosed (line 773) | private void ServerConfigWindowClosed(object sender, EventArgs e)
    method ShowConfigForm (line 788) | private void ShowConfigForm(int index)
    method ShowSettingForm (line 812) | private void ShowSettingForm()
    method ShowDnsSettingWindow (line 831) | private void ShowDnsSettingWindow()
    method ShowPortMapForm (line 850) | private void ShowPortMapForm()
    method ShowServerLogForm (line 874) | private void ShowServerLogForm()
    method ShowGlobalLogWindow (line 899) | private void ShowGlobalLogWindow()
    method ShowSubscribeSettingForm (line 923) | private void ShowSubscribeSettingForm()
    method Config_Click (line 947) | private void Config_Click(object sender, EventArgs e)
    method Controller_ShowSubscribeWindowEvent (line 959) | private void Controller_ShowSubscribeWindowEvent(object sender, EventA...
    method Import_Click (line 964) | private void Import_Click(object sender, RoutedEventArgs e)
    method Setting_Click (line 988) | private void Setting_Click(object sender, RoutedEventArgs e)
    method DnsSetting_Click (line 993) | private void DnsSetting_Click(object sender, RoutedEventArgs e)
    method Quit_Click (line 998) | public void Quit_Click(object sender, EventArgs e)
    method OpenWiki_Click (line 1025) | private static void OpenWiki_Click(object sender, RoutedEventArgs e)
    method FeedbackItem_Click (line 1030) | private static void FeedbackItem_Click(object sender, RoutedEventArgs e)
    method notifyIcon_TrayLeftMouseUp (line 1035) | private void notifyIcon_TrayLeftMouseUp(object sender, RoutedEventArgs e)
    method notifyIcon_TrayMiddleMouseUp (line 1065) | private void notifyIcon_TrayMiddleMouseUp(object sender, RoutedEventAr...
    method NoModifyItem_Click (line 1070) | private void NoModifyItem_Click(object sender, RoutedEventArgs e)
    method EnableItem_Click (line 1075) | private void EnableItem_Click(object sender, RoutedEventArgs e)
    method GlobalModeItem_Click (line 1080) | private void GlobalModeItem_Click(object sender, RoutedEventArgs e)
    method PACModeItem_Click (line 1085) | private void PACModeItem_Click(object sender, RoutedEventArgs e)
    method RuleBypassLanItem_Click (line 1090) | private void RuleBypassLanItem_Click(object sender, RoutedEventArgs e)
    method RuleBypassChinaItem_Click (line 1095) | private void RuleBypassChinaItem_Click(object sender, RoutedEventArgs e)
    method RuleBypassNotChinaItem_Click (line 1100) | private void RuleBypassNotChinaItem_Click(object sender, RoutedEventAr...
    method RuleUserItem_Click (line 1105) | private void RuleUserItem_Click(object sender, RoutedEventArgs e)
    method RuleBypassDisableItem_Click (line 1110) | private void RuleBypassDisableItem_Click(object sender, RoutedEventArg...
    method SelectRandomItem_Click (line 1115) | private void SelectRandomItem_Click(object sender, RoutedEventArgs e)
    method AutoCheckUpdateItem_Click (line 1128) | private void AutoCheckUpdateItem_Click(object sender, RoutedEventArgs e)
    method AllowPreRelease_Click (line 1134) | private void AllowPreRelease_Click(object sender, RoutedEventArgs e)
    method SelectSameHostForSameTargetItem_Click (line 1140) | private void SelectSameHostForSameTargetItem_Click(object sender, Rout...
    method CopyPacUrlItem_Click (line 1153) | private void CopyPacUrlItem_Click(object sender, RoutedEventArgs e)
    method EditPACFileItem_Click (line 1158) | private void EditPACFileItem_Click(object sender, RoutedEventArgs e)
    method UpdatePACFromGFWListItem_Click (line 1163) | private void UpdatePACFromGFWListItem_Click(object sender, RoutedEvent...
    method UpdatePACFromLanIPListItem_Click (line 1168) | private void UpdatePACFromLanIPListItem_Click(object sender, RoutedEve...
    method UpdatePACFromCNWhiteListItem_Click (line 1173) | private void UpdatePACFromCNWhiteListItem_Click(object sender, RoutedE...
    method UpdatePACFromCNOnlyListItem_Click (line 1179) | private void UpdatePACFromCNOnlyListItem_Click(object sender, RoutedEv...
    method UpdatePACFromCnWhiteListIpItem_Click (line 1185) | private void UpdatePACFromCnWhiteListIpItem_Click(object sender, Route...
    method UpdatePACFromChnIpItem_Click (line 1191) | private void UpdatePACFromChnIpItem_Click(object sender, RoutedEventAr...
    method EditUserRuleFileForGFWListItem_Click (line 1197) | private void EditUserRuleFileForGFWListItem_Click(object sender, Route...
    method AServerItem_Click (line 1202) | private void AServerItem_Click(object sender, EventArgs e)
    method CheckUpdate_Click (line 1213) | private void CheckUpdate_Click(object sender, RoutedEventArgs e)
    method CheckNodeUpdate_Click (line 1218) | private void CheckNodeUpdate_Click(object sender, RoutedEventArgs e)
    method ShowLogItem_Click (line 1223) | private void ShowLogItem_Click(object sender, RoutedEventArgs e)
    method ShowPortMapItem_Click (line 1228) | private void ShowPortMapItem_Click(object sender, RoutedEventArgs e)
    method ShowServerLogItem_Click (line 1233) | private void ShowServerLogItem_Click(object sender, RoutedEventArgs e)
    method SubscribeSetting_Click (line 1238) | private void SubscribeSetting_Click(object sender, RoutedEventArgs e)
    method DisconnectCurrent_Click (line 1243) | private void DisconnectCurrent_Click(object sender, RoutedEventArgs e)
    method ImportAddress (line 1248) | public void ImportAddress(string text)
    method ImportSsrUrl (line 1255) | private void ImportSsrUrl(string text)
    method ImportSubUrl (line 1263) | private void ImportSubUrl(string text)
    method ImportAddressFromClipboard_Click (line 1271) | private void ImportAddressFromClipboard_Click(object sender, RoutedEve...
    method ScanQRCodeItem_Click (line 1289) | private void ScanQRCodeItem_Click(object sender, RoutedEventArgs e)
    method Splash_Closed (line 1382) | private void Splash_Closed(object sender, EventArgs e)
    method Splash_Closed0 (line 1387) | private void Splash_Closed0(object sender, EventArgs e)
    method ShowUrlFromQrCode (line 1392) | private void ShowUrlFromQrCode()
    method Splash_Closed2 (line 1400) | private void Splash_Closed2(object sender, EventArgs e)
    method ShowUrlFromQrCode (line 1405) | private void ShowUrlFromQrCode(object sender, RoutedEventArgs e)

FILE: shadowsocks-csharp/Controller/Service/HostDaemon.cs
  class HostDaemon (line 8) | public class HostDaemon
    method HostDaemon (line 16) | public HostDaemon()
    method WatchChnIp (line 22) | private void WatchChnIp()
    method WatchUserRule (line 37) | private void WatchUserRule()
    method UserRuleWatcher_Changed (line 52) | private void UserRuleWatcher_Changed(object sender, FileSystemEventArg...
    method ChnIpWatcher_Changed (line 71) | private void ChnIpWatcher_Changed(object sender, FileSystemEventArgs e)

FILE: shadowsocks-csharp/Controller/Service/HostMap.cs
  class HostMap (line 9) | public static class HostMap
    method HostMap (line 16) | static HostMap()
    method Clear (line 21) | private static void Clear()
    method Reload (line 27) | public static void Reload()
    method AddHost (line 33) | private static void AddHost(string host, string addr)
    method GetHost (line 69) | public static bool GetHost(string host, out string addr)
    method GetIP (line 99) | public static bool GetIP(IPAddress ip, out string addr)
    method LoadHostFile (line 106) | private static void LoadHostFile()

FILE: shadowsocks-csharp/Controller/Service/HttpPortForwarder.cs
  class HttpPortForwarder (line 10) | internal class HttpPortForwarder : Listener.Service
    method HttpPortForwarder (line 15) | public HttpPortForwarder(int targetPort, Configuration config)
    method Handle (line 21) | public override bool Handle(byte[] firstPacket, int length, Socket soc...
    class Handler (line 31) | private class Handler
      method Start (line 51) | public void Start(Configuration config, byte[] firstPacket, int leng...
      method RspHttpHandshakeReceive (line 69) | private void RspHttpHandshakeReceive()
      method HttpHandshakeRecv (line 111) | private void HttpHandshakeRecv(IAsyncResult ar)
      method HttpHandshakeAuthEndSend (line 139) | private void HttpHandshakeAuthEndSend(IAsyncResult ar)
      method StartConnect (line 158) | private void StartConnect(IAsyncResult ar)
      method Connect (line 173) | private void Connect()
      method ConnectCallback (line 192) | private void ConnectCallback(IAsyncResult ar)
      method HandshakeReceive (line 211) | private void HandshakeReceive()
      method StartPipe (line 228) | private void StartPipe(IAsyncResult ar)
      method PipeRemoteReceiveCallback (line 247) | private void PipeRemoteReceiveCallback(IAsyncResult ar)
      method PipeConnectionReceiveCallback (line 275) | private void PipeConnectionReceiveCallback(IAsyncResult ar)
      method PipeRemoteSendCallback (line 303) | private void PipeRemoteSendCallback(IAsyncResult ar)
      method PipeConnectionSendCallback (line 322) | private void PipeConnectionSendCallback(IAsyncResult ar)
      method CheckClose (line 341) | private void CheckClose()
      method Close (line 349) | private void Close()

FILE: shadowsocks-csharp/Controller/Service/HttpProxyRunner.cs
  class HttpProxyRunner (line 11) | public class HttpProxyRunner
    method Start (line 17) | public void Start(Configuration configuration)
    method Stop (line 41) | public void Stop()

FILE: shadowsocks-csharp/Controller/Service/Listener.cs
  class Listener (line 14) | public class Listener
    type IService (line 16) | public interface IService
      method Handle (line 18) | bool Handle(byte[] firstPacket, int length, Socket socket);
      method Stop (line 20) | void Stop();
    class Service (line 23) | public abstract class Service : IService
      method Handle (line 25) | public abstract bool Handle(byte[] firstPacket, int length, Socket s...
      method Stop (line 27) | public virtual void Stop() { }
    method Listener (line 38) | public Listener(List<IService> services)
    method CheckIfPortInUse (line 44) | private static bool CheckIfPortInUse(int port)
    method Start (line 50) | public void Start(Configuration config, int port)
    method Stop (line 119) | public void Stop()
    method AcceptCallback (line 137) | private void AcceptCallback(IAsyncResult ar)
    method ReceiveCallback (line 208) | private void ReceiveCallback(IAsyncResult ar)

FILE: shadowsocks-csharp/Controller/Service/Local.cs
  class Local (line 11) | public class Local : Listener.Service
    method Local (line 17) | public Local(Configuration config, ServerTransferTotal transfer, IPRan...
    method Accept (line 24) | private static bool Accept(byte[] firstPacket, int length)
    method Handle (line 50) | public override bool Handle(byte[] firstPacket, int length, Socket soc...

FILE: shadowsocks-csharp/Controller/Service/PACDaemon.cs
  class PACDaemon (line 12) | public class PACDaemon
    method PACDaemon (line 24) | public PACDaemon()
    method TouchPACFile (line 33) | public string TouchPACFile()
    method TouchUserRuleFile (line 42) | internal string TouchUserRuleFile()
    method GetPACContent (line 51) | internal string GetPACContent()
    method WatchPacFile (line 60) | private void WatchPacFile()
    method WatchUserRuleFile (line 75) | private void WatchUserRuleFile()
    method PACFileWatcher_Changed (line 94) | private void PACFileWatcher_Changed(object sender, FileSystemEventArgs e)
    method UserRuleFileWatcher_Changed (line 113) | private void UserRuleFileWatcher_Changed(object sender, FileSystemEven...

FILE: shadowsocks-csharp/Controller/Service/PACServer.cs
  class PACServer (line 11) | public class PACServer : Listener.Service
    method PACServer (line 26) | public PACServer(PACDaemon pacDaemon)
    method UpdatePacUrl (line 31) | public void UpdatePacUrl(Configuration config)
    method Handle (line 38) | public override bool Handle(byte[] firstPacket, int length, Socket soc...
    method SendResponse (line 130) | private void SendResponse(Socket socket, int socksType, string setProxy)
    method SendCallback (line 181) | private static void SendCallback(IAsyncResult ar)
    method GetPACAddress (line 195) | private string GetPACAddress(IPEndPoint localEndPoint, int socksType)

FILE: shadowsocks-csharp/Controller/Service/ProtocolResponseDetector.cs
  class ProtocolResponseDetector (line 5) | internal class ProtocolResponseDetector
    type Protocol (line 7) | protected enum Protocol
    method ProtocolResponseDetector (line 23) | public ProtocolResponseDetector()
    method OnSend (line 28) | public void OnSend(byte[] sendData, int length)
    method OnRecv (line 80) | public int OnRecv(byte[] recv_data, int length)
    method Finish (line 123) | private void Finish()

FILE: shadowsocks-csharp/Controller/Service/Socks5Forwarder.cs
  class Socks5Forwarder (line 15) | class Socks5Forwarder : Listener.Service
    method Socks5Forwarder (line 23) | public Socks5Forwarder(Configuration config, IPRangeSet IPRange)
    method Handle (line 29) | public override bool Handle(byte[] firstPacket, int length, Socket soc...
    method Handle (line 34) | public bool Handle(byte[] firstPacket, int length, Socket socket, stri...
    method IsHandle (line 52) | private int IsHandle(byte[] firstPacket, int length)
    class Handler (line 193) | private class Handler : IHandler
      method Start (line 218) | public void Start(Configuration config, byte[] firstPacket, Socket s...
      method Connect (line 230) | private void Connect()
      method ConnectProxyServer (line 350) | private bool ConnectProxyServer(string strRemoteHost, int iRemotePort)
      method ConnectCallback (line 367) | private void ConnectCallback(IAsyncResult ar)
      method ResetTimeout (line 392) | private void ResetTimeout(double time)
      method timer_Elapsed (line 438) | private void timer_Elapsed(object sender, ElapsedEventArgs e)
      method StartPipe (line 447) | private void StartPipe()
      method PipeRemoteReceiveCallback (line 469) | private void PipeRemoteReceiveCallback(IAsyncResult ar)
      method PipeRemoteReceiveLoop (line 506) | private void PipeRemoteReceiveLoop()
      method PipeConnectionReceiveCallback (line 559) | private void PipeConnectionReceiveCallback(IAsyncResult ar)
      method CloseSocket (line 588) | private void CloseSocket(ProxySocketTun sock)
      method Close (line 615) | public void Close()
      method Shutdown (line 632) | public override void Shutdown()

FILE: shadowsocks-csharp/Controller/Service/SpeedTest.cs
  class SpeedTester (line 9) | internal class SpeedTester
    type TransLog (line 12) | private struct TransLog
    method BeginConnect (line 34) | public void BeginConnect()
    method EndConnect (line 39) | public void EndConnect()
    method BeginUpload (line 44) | public void BeginUpload()
    method BeginDownload (line 49) | public bool BeginDownload()
    method AddDownloadSize (line 59) | public bool AddDownloadSize(int size)
    method AddProtocolRecvSize (line 80) | public void AddProtocolRecvSize(int size)
    method AddRecvSize (line 85) | public void AddRecvSize(int size)
    method AddUploadSize (line 90) | public bool AddUploadSize(int size)
    method TransferLog (line 111) | public string TransferLog()

FILE: shadowsocks-csharp/Controller/Service/UpdateSubscribeManager.cs
  class UpdateSubscribeManager (line 8) | public class UpdateSubscribeManager
    method CreateTask (line 15) | public void CreateTask(Configuration config, UpdateNode updater, bool ...
    method Next (line 47) | public void Next()

FILE: shadowsocks-csharp/Controller/SystemProxy.cs
  class SystemProxy (line 9) | public static class SystemProxy
    method SystemProxy (line 12) | static SystemProxy()
    method Restore (line 25) | public static void Restore()
    method Update (line 38) | public static void Update(Configuration config, PACServer pacSrv)

FILE: shadowsocks-csharp/Data/abp.js
  function createDict (line 31) | function createDict()
  function getOwnPropertyDescriptor (line 38) | function getOwnPropertyDescriptor(obj, key)
  function extend (line 47) | function extend(subclass, superclass, definition)
  function Filter (line 70) | function Filter(text)
  function InvalidFilter (line 106) | function InvalidFilter(text, reason)
  function CommentFilter (line 115) | function CommentFilter(text)
  function ActiveFilter (line 122) | function ActiveFilter(text, domains)
  function RegExpFilter (line 252) | function RegExpFilter(text, regexpSource, contentType, matchCase, domain...
  function BlockingFilter (line 459) | function BlockingFilter(text, regexpSource, contentType, matchCase, doma...
  function WhitelistFilter (line 468) | function WhitelistFilter(text, regexpSource, contentType, matchCase, dom...
  function Matcher (line 475) | function Matcher()
  function CombinedMatcher (line 629) | function CombinedMatcher()
  function convertAddress (line 799) | function convertAddress(ipchars) {
  function check_ipv4 (line 808) | function check_ipv4(host) {
  function check_ipv6 (line 814) | function check_ipv6(host) {
  function check_ipv6_dns (line 820) | function check_ipv6_dns(dnsstr) {
  function isInSubnetRange (line 826) | function isInSubnetRange(ipRange, intIp) {
  function getProxyFromIP (line 832) | function getProxyFromIP(strIp) {
  function FindProxyForURL (line 840) | function FindProxyForURL(url, host) {

FILE: shadowsocks-csharp/Encryption/CircularBuffer/ByteCircularBuffer.cs
  class ByteCircularBuffer (line 46) | public class ByteCircularBuffer
    method ByteCircularBuffer (line 69) | public ByteCircularBuffer(int capacity)
    method Clear (line 157) | public void Clear()
    method Contains (line 170) | public bool Contains(byte item)
    method CopyTo (line 197) | public void CopyTo(byte[] array)
    method CopyTo (line 207) | public void CopyTo(byte[] array, int arrayIndex)
    method CopyTo (line 219) | public virtual void CopyTo(int index, byte[] array, int arrayIndex, in...
    method Get (line 245) | public byte[] Get(int count)
    method Get (line 264) | public int Get(byte[] array)
    method Get (line 281) | public virtual int Get(byte[] array, int arrayIndex, int count)
    method Get (line 320) | public virtual byte Get()
    method Peek (line 342) | public virtual byte Peek()
    method Peek (line 360) | public virtual byte[] Peek(int count)
    method PeekLast (line 378) | public virtual byte PeekLast()
    method Put (line 407) | public int Put(byte[] array)
    method Put (line 420) | public virtual int Put(byte[] array, int arrayIndex, int count)
    method Put (line 456) | public virtual void Put(byte item)
    method Skip (line 490) | public void Skip(int count)
    method ToArray (line 511) | public byte[] ToArray()

FILE: shadowsocks-csharp/Encryption/CryptoUtils.cs
  class CryptoUtils (line 10) | public static class CryptoUtils
    method SsAes128 (line 12) | public static void SsAes128(string password, ReadOnlySpan<byte> source...
    method MD5 (line 27) | public static byte[] MD5(ReadOnlySpan<byte> input)
    method SHA1 (line 35) | public static byte[] SHA1(ReadOnlySpan<byte> input)

FILE: shadowsocks-csharp/Encryption/EncryptorBase.cs
  class EncryptorBase (line 3) | public abstract class EncryptorBase : IEncryptor
    method EncryptorBase (line 16) | protected EncryptorBase(string method, string password)
    method Encrypt (line 25) | public abstract void Encrypt(byte[] buf, int length, byte[] outbuf, ou...
    method Decrypt (line 27) | public abstract void Decrypt(byte[] buf, int length, byte[] outbuf, ou...
    method ResetEncrypt (line 29) | public abstract void ResetEncrypt();
    method ResetDecrypt (line 30) | public abstract void ResetDecrypt();
    method Dispose (line 32) | public abstract void Dispose();
    method getIV (line 33) | public abstract byte[] getIV();
    method getKey (line 34) | public abstract byte[] getKey();
    method getInfo (line 35) | public abstract EncryptorInfo getInfo();

FILE: shadowsocks-csharp/Encryption/EncryptorFactory.cs
  class EncryptorFactory (line 9) | public static class EncryptorFactory
    method EncryptorFactory (line 15) | static EncryptorFactory()
    method GetEncryptor (line 43) | public static IEncryptor GetEncryptor(string method, string password)
    method GetEncryptorInfo (line 60) | public static EncryptorInfo GetEncryptorInfo(string method)

FILE: shadowsocks-csharp/Encryption/EncryptorInfo.cs
  class EncryptorInfo (line 3) | public class EncryptorInfo
    method EncryptorInfo (line 11) | public EncryptorInfo(int key, int iv, int type, string innerLibName = ...

FILE: shadowsocks-csharp/Encryption/Exception/CryptoException.cs
  class CryptoErrorException (line 3) | public class CryptoErrorException : System.Exception
    method CryptoErrorException (line 5) | public CryptoErrorException()
    method CryptoErrorException (line 9) | public CryptoErrorException(string msg) : base(msg)
    method CryptoErrorException (line 13) | public CryptoErrorException(string message, System.Exception innerExce...

FILE: shadowsocks-csharp/Encryption/IEncryptor.cs
  type IEncryptor (line 5) | public interface IEncryptor : IDisposable
    method Encrypt (line 7) | void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
    method Decrypt (line 8) | void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
    method ResetEncrypt (line 9) | void ResetEncrypt();
    method ResetDecrypt (line 10) | void ResetDecrypt();
    method getIV (line 11) | byte[] getIV();
    method getKey (line 12) | byte[] getKey();
    method getInfo (line 13) | EncryptorInfo getInfo();

FILE: shadowsocks-csharp/Encryption/OpenSSL.cs
  class OpenSSL (line 12) | public static class OpenSSL
    method OpenSSL (line 19) | static OpenSSL()
    method GetCipherInfo (line 36) | public static IntPtr GetCipherInfo(string cipherName)
    method LoadLibrary (line 43) | [DllImport(@"Kernel32.dll")]
    method EVP_get_cipherbyname (line 46) | [SuppressUnmanagedCodeSecurity]
    method EVP_CIPHER_CTX_new (line 50) | [SuppressUnmanagedCodeSecurity]
    method EVP_CIPHER_CTX_free (line 54) | [SuppressUnmanagedCodeSecurity]
    method EVP_CipherInit_ex (line 58) | [SuppressUnmanagedCodeSecurity]
    method EVP_CipherUpdate (line 62) | [SuppressUnmanagedCodeSecurity]
    method EVP_CIPHER_CTX_set_padding (line 66) | [SuppressUnmanagedCodeSecurity]
    method EVP_CIPHER_CTX_set_key_length (line 70) | [SuppressUnmanagedCodeSecurity]

FILE: shadowsocks-csharp/Encryption/Sodium.cs
  class Sodium (line 10) | public static class Sodium
    method Sodium (line 17) | static Sodium()
    method LoadLibrary (line 47) | [DllImport(@"Kernel32.dll")]
    method sodium_init (line 50) | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
    method crypto_stream_salsa20_xor_ic (line 55) | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
    method crypto_stream_xsalsa20_xor_ic (line 58) | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
    method crypto_stream_chacha20_xor_ic (line 61) | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
    method crypto_stream_xchacha20_xor_ic (line 64) | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
    method crypto_stream_chacha20_ietf_xor_ic (line 67) | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]

FILE: shadowsocks-csharp/Encryption/Stream/NoneEncryptor.cs
  class NoneEncryptor (line 6) | public sealed class NoneEncryptor : StreamEncryptor
    method NoneEncryptor (line 8) | public NoneEncryptor(string method, string password) : base(method, pa...
    method SupportedCiphers (line 16) | public static List<string> SupportedCiphers()
    method getCiphers (line 21) | protected override Dictionary<string, EncryptorInfo> getCiphers()
    method CipherUpdate (line 26) | protected override void CipherUpdate(bool isCipher, int length, byte[]...
    method Dispose (line 40) | public override void Dispose()
    method Dispose (line 51) | private void Dispose(bool disposing)

FILE: shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs
  class StreamEncryptor (line 10) | public abstract class StreamEncryptor : EncryptorBase
    method StreamEncryptor (line 36) | protected StreamEncryptor(string method, string password) : base(metho...
    method getCiphers (line 42) | protected abstract Dictionary<string, EncryptorInfo> getCiphers();
    method SetIV (line 44) | public bool SetIV(byte[] iv)
    method getIV (line 55) | public override byte[] getIV()
    method getKey (line 59) | public override byte[] getKey()
    method getInfo (line 65) | public override EncryptorInfo getInfo()
    method InitEncryptorInfo (line 70) | private void InitEncryptorInfo(string method)
    method InitKey (line 87) | private void InitKey(string password)
    method InitCipher (line 97) | protected virtual void InitCipher(byte[] iv, bool isCipher)
    method CipherUpdate (line 111) | protected abstract void CipherUpdate(bool isCipher, int length, byte[]...
    method Encrypt (line 113) | public override void Encrypt(byte[] buf, int length, byte[] outbuf, ou...
    method Decrypt (line 139) | public override void Decrypt(byte[] buf, int length, byte[] outbuf, ou...
    method ResetEncrypt (line 163) | public override void ResetEncrypt()
    method ResetDecrypt (line 169) | public override void ResetDecrypt()

FILE: shadowsocks-csharp/Encryption/Stream/StreamOpenSSLEncryptor.cs
  class StreamOpenSSLEncryptor (line 8) | public sealed class StreamOpenSSLEncryptor : StreamEncryptor
    method StreamOpenSSLEncryptor (line 18) | public StreamOpenSSLEncryptor(string method, string password) : base(m...
    method SupportedCiphers (line 51) | public static List<string> SupportedCiphers()
    method getCiphers (line 56) | protected override Dictionary<string, EncryptorInfo> getCiphers()
    method InitCipher (line 61) | protected override void InitCipher(byte[] iv, bool isEncrypt)
    method CipherUpdate (line 120) | protected override void CipherUpdate(bool isCipher, int length, byte[]...
    method Dispose (line 142) | public override void Dispose()
    method Dispose (line 153) | private void Dispose(bool disposing)

FILE: shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs
  class StreamSodiumEncryptor (line 7) | public class StreamSodiumEncryptor : StreamEncryptor
    method StreamSodiumEncryptor (line 27) | public StreamSodiumEncryptor(string method, string password) : base(me...
    method getCiphers (line 51) | protected override Dictionary<string, EncryptorInfo> getCiphers()
    method SupportedCiphers (line 56) | public static List<string> SupportedCiphers()
    method CipherUpdate (line 61) | protected override void CipherUpdate(bool isCipher, int length, byte[]...
    method ResetEncrypt (line 106) | public override void ResetEncrypt()
    method ResetDecrypt (line 113) | public override void ResetDecrypt()
    method crypto_stream_chacha20_ietf_xor_ic (line 120) | private int crypto_stream_chacha20_ietf_xor_ic(byte[] c, byte[] m, ulo...
    method Dispose (line 125) | public override void Dispose()

FILE: shadowsocks-csharp/Enums/BalanceType.cs
  type BalanceType (line 3) | public enum BalanceType

FILE: shadowsocks-csharp/Enums/DnsType.cs
  type DnsType (line 3) | public enum DnsType

FILE: shadowsocks-csharp/Enums/HttpRequestProxyType.cs
  type HttpRequestProxyType (line 3) | public enum HttpRequestProxyType

FILE: shadowsocks-csharp/Enums/LogLevel.cs
  type LogLevel (line 3) | public enum LogLevel

FILE: shadowsocks-csharp/Enums/PacType.cs
  type PacType (line 3) | public enum PacType

FILE: shadowsocks-csharp/Enums/PortMapType.cs
  type PortMapType (line 3) | public enum PortMapType

FILE: shadowsocks-csharp/Enums/ProxyMode.cs
  type ProxyMode (line 3) | public enum ProxyMode

FILE: shadowsocks-csharp/Enums/ProxyRuleMode.cs
  type ProxyRuleMode (line 3) | public enum ProxyRuleMode

FILE: shadowsocks-csharp/Enums/ProxyType.cs
  type ProxyType (line 3) | public enum ProxyType

FILE: shadowsocks-csharp/Enums/ServerTreeViewType.cs
  type ServerTreeViewType (line 3) | public enum ServerTreeViewType

FILE: shadowsocks-csharp/Model/Configuration.cs
  class Configuration (line 11) | [Serializable]
    method KeepCurrentServer (line 228) | public bool KeepCurrentServer(int port, string targetAddr, string id)
    method GetCurrentServer (line 262) | public Server GetCurrentServer(int port, ServerSelectStrategy.FilterFu...
    method FlushPortMapCache (line 376) | public void FlushPortMapCache()
    method Configuration (line 447) | public Configuration()
    method CopyFrom (line 490) | public void CopyFrom(Configuration config)
    method FixConfiguration (line 526) | public void FixConfiguration()
    method IsDefaultConfig (line 562) | public bool IsDefaultConfig()
    method GetErrorServer (line 567) | private static Server GetErrorServer()
    method IsPort (line 573) | private static bool IsPort(int port)

FILE: shadowsocks-csharp/Model/ConfigurationException.cs
  class ConfigurationException (line 5) | [Serializable]
    method ConfigurationException (line 8) | public ConfigurationException()
    method ConfigurationException (line 10) | public ConfigurationException(string message) : base(message) { }
    method ConfigurationException (line 11) | public ConfigurationException(string message, Exception inner) : base(...
    method ConfigurationException (line 12) | protected ConfigurationException(System.Runtime.Serialization.Serializ...

FILE: shadowsocks-csharp/Model/Connections.cs
  class Connections (line 6) | public class Connections
    method AddRef (line 9) | public bool AddRef(IHandler socket)
    method DecRef (line 24) | public bool DecRef(IHandler socket)
    method CloseAll (line 43) | public void CloseAll()

FILE: shadowsocks-csharp/Model/DnsBuffer.cs
  class DnsBuffer (line 6) | public class DnsBuffer
    method IsExpired (line 13) | public bool IsExpired(string host)
    method UpdateDns (line 28) | public void UpdateDns(string host, IPAddress ip)

FILE: shadowsocks-csharp/Model/DnsClient.cs
  class DnsClient (line 18) | [Serializable]
    method DnsClient (line 139) | [JsonConstructor]
    method DnsClient (line 158) | public DnsClient(DnsType type) : this()
    method IsIp (line 182) | private static bool IsIp(string? str)
    method IsValidDns (line 187) | private bool IsValidDns(string? dns)
    method QueryBaseAAsync (line 192) | private static async Task<IPAddress?> QueryBaseAAsync(ARSoft.Tools.Net...
    method QueryBaseAaaaAsync (line 206) | private static async Task<IPAddress?> QueryBaseAaaaAsync(ARSoft.Tools....
    method QueryBaseAsync (line 220) | private static async Task<IPAddress?> QueryBaseAsync(ARSoft.Tools.Net....
    method QueryBaseTlsAAsync (line 234) | private static async Task<IPAddress?> QueryBaseTlsAAsync(DnsOverTlsCli...
    method QueryBaseTlsAaaaAsync (line 248) | private static async Task<IPAddress?> QueryBaseTlsAaaaAsync(DnsOverTls...
    method QueryBaseTlsAsync (line 262) | private static async Task<IPAddress?> QueryBaseTlsAsync(DnsOverTlsClie...
    method QueryIpAddressDefaultAsync (line 278) | public static async Task<IPAddress?> QueryIpAddressDefaultAsync(string...
    method QueryIpAddressAsync (line 296) | public async Task<IPAddress?> QueryIpAddressAsync(string host, Cancell...

FILE: shadowsocks-csharp/Model/ErrorLog.cs
  class ErrorLog (line 5) | public class ErrorLog
    method ErrorLog (line 9) | public ErrorLog(int no)

FILE: shadowsocks-csharp/Model/Global.cs
  class Global (line 13) | public static class Global
    method LoadFile (line 37) | public static Configuration LoadFile(string filename)
    method Load (line 62) | public static Configuration Load()
    method Load (line 67) | private static Configuration Load(string configStr)
    method LoadConfig (line 85) | public static void LoadConfig()
    method SaveConfig (line 90) | public static void SaveConfig()

FILE: shadowsocks-csharp/Model/HostNode.cs
  class HostNode (line 5) | internal class HostNode
    method HostNode (line 11) | public HostNode()
    method HostNode (line 18) | public HostNode(bool sub, string addr)

FILE: shadowsocks-csharp/Model/IPRangeSet.cs
  class IPRangeSet (line 17) | public class IPRangeSet
    method IPRangeSet (line 24) | public IPRangeSet()
    method Reset (line 29) | [MemberNotNull(nameof(_ipMatcher))]
    method IsInIPRange (line 35) | public bool IsInIPRange(IPAddress ip)
    method LoadChn (line 45) | private bool LoadChn(IEnumerable<string?> lines)
    method LoadChn (line 76) | public void LoadChn()

FILE: shadowsocks-csharp/Model/IPSegment.cs
  class IPAddressCmp (line 7) | public class IPAddressCmp : IPAddress, IComparable
    method IPAddressCmp (line 9) | public IPAddressCmp(IPAddress ip) : base(ip.GetAddressBytes())
    method IPAddressCmp (line 13) | public IPAddressCmp(byte[] ip) : base(ip)
    method IPAddressCmp (line 17) | public IPAddressCmp(string ip) : base(FromString(ip).GetAddressBytes())
    method FromString (line 21) | public static IPAddress FromString(string ip)
    method CompareTo (line 27) | public int CompareTo(object obj)
    method ToIPv6 (line 56) | public IPAddressCmp ToIPv6()
    method Inc (line 69) | public IPAddressCmp Inc()
  class IPSegment (line 93) | public class IPSegment
    method IPSegment (line 97) | public IPSegment(object val = null)
    method insert (line 102) | public bool insert(IPAddressCmp ipStart, IPAddressCmp ipEnd, object val)
    method Get (line 184) | public object Get(IPAddressCmp ip)

FILE: shadowsocks-csharp/Model/LRUCache.cs
  class LRUCache (line 7) | public class LRUCache<K, V>
    method LRUCache (line 15) | public LRUCache(int sweep_time = 60 * 60)
    method SetTimeout (line 20) | public void SetTimeout(int time)
    method Clear (line 25) | public void Clear()
    method isTimeout (line 35) | public bool isTimeout(K key)
    method ContainsKey (line 47) | public bool ContainsKey(K key)
    method Get (line 55) | public V Get(K key)
    method Set (line 77) | public V Set(K key, V val)
    method Del (line 100) | public void Del(K key)
    method Sweep (line 115) | public void Sweep()

FILE: shadowsocks-csharp/Model/MinSearchTree.cs
  type MinSearchTreeNode (line 6) | public struct MinSearchTreeNode
  class MinSearchTree (line 14) | public class MinSearchTree
    method MinSearchTree (line 21) | public MinSearchTree(int size)
    method GetLevel (line 31) | protected int GetLevel(int size)
    method _Init (line 46) | protected void _Init(int index, int level, int range_min, int range_max)
    method Init (line 61) | public void Init()
    method Clone (line 75) | public MinSearchTree Clone()
    method Update (line 85) | public void Update(int[] add_list)
    method Update (line 99) | public void Update(Dictionary<int, long> add_map)
    method Maintain (line 117) | protected void Maintain(int index)
    method Update (line 145) | public void Update(int index, int add = 1)
    method FindMinCount (line 152) | public int FindMinCount(int index, int range_min, int range_max, out l...
    method FindNthMin (line 193) | public int FindNthMin(int index, int range_min, int range_max, int nth...
    method FindMinCount2 (line 225) | public int FindMinCount2(int index, int range_min, int range_max, out ...
    method FindNthMin2 (line 248) | public int FindNthMin2(int range_min, int range_max, int nth)
    method RandomFindIndex (line 275) | public int RandomFindIndex(int range_min, int range_max, Random random)
    method GetMin (line 283) | public long GetMin(int range_min, int range_max)

FILE: shadowsocks-csharp/Model/PortMapConfig.cs
  class PortMapConfig (line 7) | [Serializable]

FILE: shadowsocks-csharp/Model/PortMapConfigCache.cs
  class PortMapConfigCache (line 5) | public class PortMapConfigCache

FILE: shadowsocks-csharp/Model/Rule.cs
  type Rule (line 3) | public enum Rule : byte

FILE: shadowsocks-csharp/Model/Server.cs
  class Server (line 12) | [Serializable]
    method CopyServer (line 319) | public void CopyServer(Server oldServer)
    method Clone (line 329) | public object Clone()
    method Clone (line 351) | public static Server Clone(Server serverObject)
    method Server (line 370) | public Server()
    method Server (line 391) | public Server(string ssUrl, string forceGroup) : this()
    method ParseParam (line 407) | private static Dictionary<string, string> ParseParam(string paramStr)
    method ServerFromSsr (line 424) | public void ServerFromSsr(string ssrUrl, string forceGroup)
    method ServerFromSs (line 492) | private void ServerFromSs(string ssUrl, string forceGroup)
    method IsMatchServer (line 515) | public bool IsMatchServer(Server serverObject)
    method SetField (line 533) | protected override bool SetField<T>(ref T field, T value, string prope...

FILE: shadowsocks-csharp/Model/ServerSelectStrategy.cs
  class ServerSelectStrategy (line 8) | public class ServerSelectStrategy
    type ServerIndex (line 21) | private struct ServerIndex
      method ServerIndex (line 25) | public ServerIndex(int i, Server s)
    method lowerBound (line 31) | private int lowerBound(List<double> data, double target)
    method Algorithm2 (line 50) | private double Algorithm2(ServerSpeedLog serverSpeedLog) // perfer les...
    method Algorithm3 (line 94) | private double Algorithm3(ServerSpeedLog serverSpeedLog) // perfer les...
    method Algorithm4 (line 138) | private double Algorithm4(ServerSpeedLog serverSpeedLog, long avg_spee...
    method SubSelect (line 186) | protected int SubSelect(IList<Server> configs, int curIndex, BalanceTy...
    method Select (line 422) | public int Select(IList<Server> configs, int curIndex, BalanceType alg...

FILE: shadowsocks-csharp/Model/ServerSubscribe.cs
  class ServerSubscribe (line 11) | [Serializable]
    method ServerSubscribe (line 20) | public ServerSubscribe()

FILE: shadowsocks-csharp/Model/ServerTreeViewModel.cs
  class ServerTreeViewModel (line 11) | public class ServerTreeViewModel : ViewModelBase
    method ServerTreeViewModel (line 13) | public ServerTreeViewModel()
    method Server_ServerChanged (line 82) | private void Server_ServerChanged(object sender, EventArgs e)
    method Remove (line 89) | public static void Remove(ObservableCollection<ServerTreeViewModel> ro...
    method FindParentNode (line 102) | public static ServerTreeViewModel FindParentNode(Collection<ServerTree...
    method FindNode (line 123) | public static ServerTreeViewModel FindNode(Collection<ServerTreeViewMo...

FILE: shadowsocks-csharp/Model/Transfer/ServerSpeedLog.cs
  class ServerSpeedLog (line 12) | public class ServerSpeedLog : ViewModelBase
    method ServerSpeedLog (line 33) | public ServerSpeedLog() { }
    method ServerSpeedLog (line 35) | public ServerSpeedLog(long upload, long download)
    method GetTransSpeed (line 41) | public void GetTransSpeed(out long upload, out long download)
    method ClearTrans (line 241) | public void ClearTrans()
    method ClearError (line 252) | public void ClearError()
    method ClearMaxSpeed (line 283) | public void ClearMaxSpeed()
    method Clear (line 294) | public void Clear()
    method AddConnectTimes (line 305) | public void AddConnectTimes()
    method AddDisconnectTimes (line 313) | public void AddDisconnectTimes()
    method Sweep (line 321) | private void Sweep()
    method AddNoErrorTimes (line 379) | public void AddNoErrorTimes()
    method AddErrorTimes (line 388) | public void AddErrorTimes()
    method AddTimeoutTimes (line 400) | public void AddTimeoutTimes()
    method AddErrorDecodeTimes (line 412) | public void AddErrorDecodeTimes()
    method AddErrorEmptyTimes (line 424) | public void AddErrorEmptyTimes()
    method UpdateTransLog (line 436) | private static void UpdateTransLog(IList<TransLog> transLog, int bytes...
    method AddUploadBytes (line 514) | public void AddUploadBytes(int bytes, DateTime now, bool updateMaxTrans)
    method AddDownloadBytes (line 530) | public void AddDownloadBytes(int bytes, DateTime now, bool updateMaxTr...
    method AddDownloadRawBytes (line 546) | public void AddDownloadRawBytes(long bytes)
    method ResetErrorDecodeTimes (line 553) | public void ResetErrorDecodeTimes()
    method ResetContinuousTimes (line 566) | public void ResetContinuousTimes()
    method ResetEmptyTimes (line 575) | public void ResetEmptyTimes()
    method ResetConnectTime (line 581) | public void ResetConnectTime()
    method AddConnectTime (line 587) | public void AddConnectTime(long millisecond)

FILE: shadowsocks-csharp/Model/Transfer/ServerTrans.cs
  class ServerTrans (line 5) | [Serializable]

FILE: shadowsocks-csharp/Model/Transfer/ServerTransferTotal.cs
  class ServerTransferTotal (line 10) | [Serializable]
    method Load (line 22) | public static ServerTransferTotal Load()
    method Init (line 52) | private void Init()
    method Save (line 62) | public static void Save(ServerTransferTotal config, List<Server> serve...
    method Clear (line 81) | public void Clear(string serverId)
    method AddUpload (line 93) | public void AddUpload(string serverId, long size)
    method AddDownload (line 120) | public void AddDownload(string server, long size)

FILE: shadowsocks-csharp/Model/Transfer/TransLog.cs
  class TransLog (line 5) | public class TransLog
    method TransLog (line 12) | public TransLog(int s, DateTime t)

FILE: shadowsocks-csharp/Model/UriVisitTime.cs
  class UriVisitTime (line 5) | public class UriVisitTime : IComparable
    method CompareTo (line 11) | public int CompareTo(object other)

FILE: shadowsocks-csharp/Model/WindowStatus.cs
  class WindowStatus (line 6) | public class WindowStatus
    method WindowStatus (line 14) | public WindowStatus()
    method WindowStatus (line 23) | public WindowStatus(Window window)
    method SetStatus (line 32) | public void SetStatus(Window window)

FILE: shadowsocks-csharp/Obfs/AuthAES128SHA1.cs
  class AuthDataAes128 (line 18) | protected class AuthDataAes128 : AuthData
  method AuthAES128SHA1 (line 23) | public AuthAES128SHA1(string method)
  method SupportedObfs (line 68) | public static List<string> SupportedObfs()
  method GetObfs (line 73) | public override Dictionary<string, int[]> GetObfs()
  method InitData (line 78) | public override object InitData()
  method isKeepAlive (line 83) | public override bool isKeepAlive()
  method isAlwaysSendback (line 88) | public override bool isAlwaysSendback()
  method GetOverhead (line 93) | public override int GetOverhead()
  method CreateHMAC (line 98) | protected IMac CreateHMAC(byte[] key)
  method Sync (line 108) | protected void Sync()
  method RandomInMin (line 126) | protected int RandomInMin(int dataLengthMin, int dataLengthMax)
  method AddPacket (line 136) | protected void AddPacket(int length)
  method StatisticsInit (line 166) | protected void StatisticsInit(AuthDataAes128 authData)
  method GetRandLen (line 179) | protected int GetRandLen(int datalength, int fulldatalength, bool nopadd...
  method GenRandLenFull (line 203) | protected int GenRandLenFull(int packetlength, int fulldatalength, bool ...
  method GenRandLen (line 221) | protected int GenRandLen(int packetlength, int maxpacketlength)
  method PackData (line 227) | public void PackData(byte[] data, int datalength, int fulldatalength, by...
  method PackAuthData (line 279) | public void PackAuthData(byte[] data, int datalength, byte[] outdata, ou...

FILE: shadowsocks-csharp/Obfs/AuthAkarin.cs
  class AuthAkarin (line 14) | internal class AuthAkarin : VerifySimpleBase
    class AuthDataAesChain (line 16) | protected class AuthDataAesChain : AuthData
    method AuthAkarin (line 20) | public AuthAkarin(string method)
    method SupportedObfs (line 57) | public static List<string> SupportedObfs()
    method GetObfs (line 62) | public override Dictionary<string, int[]> GetObfs()
    method Disposing (line 67) | protected override void Disposing()
    method InitData (line 76) | public override object InitData()
    method isKeepAlive (line 81) | public override bool isKeepAlive()
    method isAlwaysSendback (line 86) | public override bool isAlwaysSendback()
    method GetOverhead (line 91) | public override int GetOverhead()
    method CreateHMAC (line 96) | protected IMac CreateHMAC(byte[] key)
    method GetSendRandLen (line 101) | protected virtual int GetSendRandLen(int datalength, xorshift128plus r...
    method GetRecvRandLen (line 133) | protected virtual int GetRecvRandLen(int datalength, xorshift128plus r...
    method UdpGetRandLen (line 165) | protected int UdpGetRandLen(xorshift128plus rd, byte[] last_hash)
    method GetSendRandLen (line 171) | protected int GetSendRandLen(int datalength)
    method PackData (line 176) | public void PackData(byte[] data, int datalength, byte[] outdata, out ...
    method PackAuthData (line 235) | public void PackAuthData(byte[] data, int datalength, byte[] outdata, ...
    method ClientPreEncrypt (line 355) | public override byte[] ClientPreEncrypt(byte[] plaindata, int dataleng...
    method ClientPostDecrypt (line 448) | public override byte[] ClientPostDecrypt(byte[] plaindata, int datalen...
    method ClientUdpPreEncrypt (line 512) | public override byte[] ClientUdpPreEncrypt(byte[] plaindata, int datal...
    method ClientUdpPostDecrypt (line 574) | public override byte[] ClientUdpPostDecrypt(byte[] plaindata, int data...

FILE: shadowsocks-csharp/Obfs/AuthAkarin_spec_a.cs
  class AuthAkarin_spec_a (line 5) | class AuthAkarin_spec_a : AuthAkarin
    method AuthAkarin_spec_a (line 7) | public AuthAkarin_spec_a(string method)
    method SupportedObfs (line 21) | public static new List<string> SupportedObfs()
    method GetObfs (line 26) | public override Dictionary<string, int[]> GetObfs()
    method InitDataSizeList (line 31) | protected void InitDataSizeList()
    method SetServerInfo (line 54) | public override void SetServerInfo(ServerInfo serverInfo)
    method FindPos (line 60) | protected int FindPos(int[] arr, int key)
    method GetSendRandLen (line 85) | protected override int GetSendRandLen(int datalength, xorshift128plus ...
    method GetRecvRandLen (line 134) | protected override int GetRecvRandLen(int datalength, xorshift128plus ...

FILE: shadowsocks-csharp/Obfs/AuthChain_a.cs
  class AuthChain_a (line 13) | class AuthChain_a : VerifySimpleBase
    class AuthDataAesChain (line 15) | protected class AuthDataAesChain : AuthData
    method AuthChain_a (line 19) | public AuthChain_a(string method)
    method SupportedObfs (line 53) | public static List<string> SupportedObfs()
    method GetObfs (line 58) | public override Dictionary<string, int[]> GetObfs()
    method Disposing (line 63) | protected override void Disposing()
    method InitData (line 72) | public override object InitData()
    method isKeepAlive (line 77) | public override bool isKeepAlive()
    method isAlwaysSendback (line 82) | public override bool isAlwaysSendback()
    method GetOverhead (line 87) | public override int GetOverhead()
    method CreateHMAC (line 92) | protected IMac CreateHMAC(byte[] key)
    method GetRandLen (line 97) | protected virtual int GetRandLen(int datalength, xorshift128plus rd, b...
    method UdpGetRandLen (line 123) | protected int UdpGetRandLen(xorshift128plus rd, byte[] last_hash)
    method GetRandStartPos (line 129) | protected int GetRandStartPos(int rand_len, xorshift128plus rd)
    method GetRandLen (line 139) | protected int GetRandLen(int datalength)
    method PackData (line 144) | public void PackData(byte[] data, int datalength, byte[] outdata, out ...
    method OnInitAuthData (line 190) | public virtual void OnInitAuthData(ulong unixTimestamp)
    method PackAuthData (line 195) | public void PackAuthData(byte[] data, int datalength, byte[] outdata, ...
    method ClientPreEncrypt (line 304) | public override byte[] ClientPreEncrypt(byte[] plaindata, int dataleng...
    method ClientPostDecrypt (line 397) | public override byte[] ClientPostDecrypt(byte[] plaindata, int datalen...
    method ClientUdpPreEncrypt (line 468) | public override byte[] ClientUdpPreEncrypt(byte[] plaindata, int datal...
    method ClientUdpPostDecrypt (line 525) | public override byte[] ClientUdpPostDecrypt(byte[] plaindata, int data...

FILE: shadowsocks-csharp/Obfs/AuthChain_b.cs
  class AuthChain_b (line 5) | class AuthChain_b : AuthChain_a
    method AuthChain_b (line 7) | public AuthChain_b(string method)
    method SupportedObfs (line 21) | public static new List<string> SupportedObfs()
    method GetObfs (line 26) | public override Dictionary<string, int[]> GetObfs()
    method InitDataSizeList (line 31) | protected virtual void InitDataSizeList()
    method SetServerInfo (line 54) | public override void SetServerInfo(ServerInfo serverInfo)
    method FindPos (line 60) | protected int FindPos(int[] arr, int key)
    method GetRandLen (line 85) | protected override int GetRandLen(int datalength, xorshift128plus rd, ...

FILE: shadowsocks-csharp/Obfs/AuthChain_c.cs
  class AuthChain_c (line 5) | class AuthChain_c : AuthChain_b
    method AuthChain_c (line 7) | public AuthChain_c(string method)
    method SupportedObfs (line 20) | public static new List<string> SupportedObfs()
    method GetObfs (line 25) | public override Dictionary<string, int[]> GetObfs()
    method InitDataSizeList (line 30) | protected override void InitDataSizeList()
    method SetServerInfo (line 44) | public override void SetServerInfo(ServerInfo serverInfo)
    method GetRandLen (line 50) | protected override int GetRandLen(int datalength, xorshift128plus rd, ...

FILE: shadowsocks-csharp/Obfs/AuthChain_d.cs
  class AuthChain_d (line 5) | class AuthChain_d : AuthChain_c
    method AuthChain_d (line 7) | public AuthChain_d(string method)
    method SupportedObfs (line 18) | public static new List<string> SupportedObfs()
    method GetObfs (line 23) | public override Dictionary<string, int[]> GetObfs()
    method CheckAndPatchDataSize (line 28) | protected void CheckAndPatchDataSize(List<int> data_list, xorshift128p...
    method InitDataSizeList (line 37) | protected override void InitDataSizeList()
    method SetServerInfo (line 57) | public override void SetServerInfo(ServerInfo serverInfo)
    method GetRandLen (line 63) | protected override int GetRandLen(int datalength, xorshift128plus rd, ...

FILE: shadowsocks-csharp/Obfs/AuthChain_e.cs
  class AuthChain_e (line 5) | class AuthChain_e : AuthChain_d
    method AuthChain_e (line 7) | public AuthChain_e(string method)
    method SupportedObfs (line 18) | public static new List<string> SupportedObfs()
    method GetObfs (line 23) | public override Dictionary<string, int[]> GetObfs()
    method GetRandLen (line 28) | protected override int GetRandLen(int datalength, xorshift128plus rd, ...

FILE: shadowsocks-csharp/Obfs/AuthChain_f.cs
  class AuthChain_f (line 6) | class AuthChain_f : AuthChain_e
    method AuthChain_f (line 8) | public AuthChain_f(string method)
    method SupportedObfs (line 19) | public static new List<string> SupportedObfs()
    method GetObfs (line 24) | public override Dictionary<string, int[]> GetObfs()
    method InitDataSizeList (line 33) | protected override void InitDataSizeList()
    method SetServerInfo (line 59) | public override void SetServerInfo(ServerInfo serverInfo)
    method OnInitAuthData (line 77) | public override void OnInitAuthData(ulong unixTimestamp)

FILE: shadowsocks-csharp/Obfs/AuthData.cs
  class AuthData (line 3) | public class AuthData : VerifyData

FILE: shadowsocks-csharp/Obfs/AuthSHA1.cs
  class AuthSHA1 (line 9) | public class AuthSHA1 : VerifySimpleBase
    method AuthSHA1 (line 11) | public AuthSHA1(string method)
    method SupportedObfs (line 25) | public static List<string> SupportedObfs()
    method GetObfs (line 30) | public override Dictionary<string, int[]> GetObfs()
    method InitData (line 35) | public override object InitData()
    method PackData (line 40) | public void PackData(byte[] data, int datalength, byte[] outdata, out ...
    method PackAuthData (line 56) | public void PackAuthData(byte[] data, int datalength, byte[] outdata, ...
    method ClientPreEncrypt (line 101) | public override byte[] ClientPreEncrypt(byte[] plaindata, int dataleng...
    method ClientPostDecrypt (line 148) | public override byte[] ClientPostDecrypt(byte[] plaindata, int datalen...

FILE: shadowsocks-csharp/Obfs/AuthSHA1V2.cs
  class AuthSHA1V2 (line 9) | public class AuthSHA1V2 : VerifySimpleBase
    method AuthSHA1V2 (line 11) | public AuthSHA1V2(string method)
    method SupportedObfs (line 25) | public static List<string> SupportedObfs()
    method GetObfs (line 30) | public override Dictionary<string, int[]> GetObfs()
    method InitData (line 35) | public override object InitData()
    method isKeepAlive (line 40) | public override bool isKeepAlive()
    method isAlwaysSendback (line 45) | public override bool isAlwaysSendback()
    method PackData (line 50) | public void PackData(byte[] data, int datalength, byte[] outdata, out ...
    method PackAuthData (line 80) | public void PackAuthData(byte[] data, int datalength, byte[] outdata, ...
    method ClientPreEncrypt (line 140) | public override byte[] ClientPreEncrypt(byte[] plaindata, int dataleng...
    method ClientPostDecrypt (line 193) | public override byte[] ClientPostDecrypt(byte[] plaindata, int datalen...

FILE: shadowsocks-csharp/Obfs/AuthSHA1V4.cs
  class AuthSHA1V4 (line 9) | public class AuthSHA1V4 : VerifySimpleBase
    method AuthSHA1V4 (line 11) | public AuthSHA1V4(string method)
    method SupportedObfs (line 27) | public static List<string> SupportedObfs()
    method GetObfs (line 32) | public override Dictionary<string, int[]> GetObfs()
    method InitData (line 37) | public override object InitData()
    method isKeepAlive (line 42) | public override bool isKeepAlive()
    method isAlwaysSendback (line 47) | public override bool isAlwaysSendback()
    method GetOverhead (line 52) | public override int GetOverhead()
    method PackData (line 57) | public void PackData(byte[] data, int datalength, byte[] outdata, out ...
    method PackAuthData (line 89) | public void PackAuthData(byte[] data, int datalength, byte[] outdata, ...
    method ClientPreEncrypt (line 154) | public override byte[] ClientPreEncrypt(byte[] plaindata, int dataleng...
    method ClientPostDecrypt (line 207) | public override byte[] ClientPostDecrypt(byte[] plaindata, int datalen...

FILE: shadowsocks-csharp/Obfs/HttpSimpleObfs.cs
  class HttpSimpleObfs (line 6) | class HttpSimpleObfs : ObfsBase
    method HttpSimpleObfs (line 8) | public HttpSimpleObfs(string method)
    method SupportedObfs (line 56) | public static List<string> SupportedObfs()
    method GetObfs (line 61) | public override Dictionary<string, int[]> GetObfs()
    method data2urlencode (line 66) | private string data2urlencode(byte[] encryptdata, int datalength)
    method boundary (line 76) | private string boundary()
    method ClientEncode (line 87) | public override byte[] ClientEncode(byte[] encryptdata, int datalength...
    method FindSubArray (line 205) | private int FindSubArray(byte[] array, int length, byte[] subArray)
    method ClientDecode (line 225) | public override byte[] ClientDecode(byte[] encryptdata, int datalength...

FILE: shadowsocks-csharp/Obfs/IObfs.cs
  type IObfs (line 5) | public interface IObfs : IDisposable
    method Name (line 7) | string Name();
    method isKeepAlive (line 8) | bool isKeepAlive();
    method isAlwaysSendback (line 9) | bool isAlwaysSendback();
    method ClientPreEncrypt (line 10) | byte[] ClientPreEncrypt(byte[] plaindata, int datalength, out int outl...
    method ClientEncode (line 11) | byte[] ClientEncode(byte[] encryptdata, int datalength, out int outlen...
    method ClientDecode (line 12) | byte[] ClientDecode(byte[] encryptdata, int datalength, out int outlen...
    method ClientPostDecrypt (line 13) | byte[] ClientPostDecrypt(byte[] plaindata, int datalength, out int out...
    method ClientUdpPreEncrypt (line 14) | byte[] ClientUdpPreEncrypt(byte[] plaindata, int datalength, out int o...
    method ClientUdpPostDecrypt (line 15) | byte[] ClientUdpPostDecrypt(byte[] plaindata, int datalength, out int ...
    method InitData (line 16) | object InitData();
    method SetServerInfo (line 17) | void SetServerInfo(ServerInfo serverInfo);
    method SetServerInfoIV (line 18) | void SetServerInfoIV(byte[] iv);
    method GetSentLength (line 19) | long GetSentLength();
    method GetOverhead (line 20) | int GetOverhead();
    method GetTcpMSS (line 21) | int GetTcpMSS();

FILE: shadowsocks-csharp/Obfs/ObfsBase.cs
  class ObfsBase (line 7) | public abstract class ObfsBase : IObfs
    method ObfsBase (line 9) | protected ObfsBase(string method)
    method GetObfs (line 18) | public abstract Dictionary<string, int[]> GetObfs();
    method Name (line 20) | public string Name()
    method isKeepAlive (line 25) | public virtual bool isKeepAlive()
    method isAlwaysSendback (line 30) | public virtual bool isAlwaysSendback()
    method ClientPreEncrypt (line 36) | public virtual byte[] ClientPreEncrypt(byte[] plaindata, int datalengt...
    method ClientEncode (line 41) | public abstract byte[] ClientEncode(byte[] encryptdata, int datalength...
    method ClientDecode (line 42) | public abstract byte[] ClientDecode(byte[] encryptdata, int datalength...
    method ClientPostDecrypt (line 43) | public virtual byte[] ClientPostDecrypt(byte[] plaindata, int dataleng...
    method ClientUdpPreEncrypt (line 48) | public virtual byte[] ClientUdpPreEncrypt(byte[] plaindata, int datale...
    method ClientUdpPostDecrypt (line 53) | public virtual byte[] ClientUdpPostDecrypt(byte[] plaindata, int datal...
    method InitData (line 59) | public virtual object InitData()
    method SetServerInfo (line 63) | public virtual void SetServerInfo(ServerInfo serverInfo)
    method SetServerInfoIV (line 67) | public virtual void SetServerInfoIV(byte[] iv)
    method GetHeadSize (line 71) | public static int GetHeadSize(byte[] plaindata, int defaultValue)
    method GetSentLength (line 101) | public long GetSentLength()
    method GetOverhead (line 105) | public virtual int GetOverhead()
    method GetTcpMSS (line 110) | public int GetTcpMSS()
    method Dispose (line 119) | public void Dispose()
    method Dispose (line 125) | protected virtual void Dispose(bool disposing)
    method Disposing (line 138) | protected virtual void Disposing()

FILE: shadowsocks-csharp/Obfs/ObfsException.cs
  class ObfsException (line 5) | public class ObfsException : Exception
    method ObfsException (line 7) | public ObfsException(string info)

FILE: shadowsocks-csharp/Obfs/ObfsFactory.cs
  class ObfsFactory (line 6) | public static class ObfsFactory
    method ObfsFactory (line 12) | static ObfsFactory()
    method GetObfs (line 83) | public static IObfs GetObfs(string method)

FILE: shadowsocks-csharp/Obfs/Plain.cs
  class Plain (line 5) | public class Plain : ObfsBase
    method Plain (line 7) | public Plain(string method)
    method SupportedObfs (line 17) | public static List<string> SupportedObfs()
    method GetObfs (line 22) | public override Dictionary<string, int[]> GetObfs()
    method ClientEncode (line 27) | public override byte[] ClientEncode(byte[] encryptdata, int datalength...
    method ClientDecode (line 33) | public override byte[] ClientDecode(byte[] encryptdata, int datalength...

FILE: shadowsocks-csharp/Obfs/ProtocolException.cs
  class ProtocolException (line 5) | public class ProtocolException : Exception
    method ProtocolException (line 7) | public ProtocolException(string info) : base(info)

FILE: shadowsocks-csharp/Obfs/ServerInfo.cs
  class ServerInfo (line 3) | public class ServerInfo
    method ServerInfo (line 17) | public ServerInfo(string host, int port, string param, object data, by...
    method SetIV (line 32) | public void SetIV(byte[] iv)

FILE: shadowsocks-csharp/Obfs/TlsAuthData.cs
  class TlsAuthData (line 5) | public class TlsAuthData

FILE: shadowsocks-csharp/Obfs/TlsTicketAuthObfs.cs
  class TlsTicketAuthObfs (line 9) | class TlsTicketAuthObfs : ObfsBase
    method TlsTicketAuthObfs (line 11) | public TlsTicketAuthObfs(string method)
    method SupportedObfs (line 35) | public static List<string> SupportedObfs()
    method GetObfs (line 40) | public override Dictionary<string, int[]> GetObfs()
    method InitData (line 45) | public override object InitData()
    method isAlwaysSendback (line 50) | public override bool isAlwaysSendback()
    method GetOverhead (line 55) | public override int GetOverhead()
    method sni (line 60) | protected byte[] sni(string url)
    method to_val (line 81) | protected byte to_val(char c)
    method to_bin (line 91) | protected byte[] to_bin(string str)
    method hmac_sha1 (line 101) | protected void hmac_sha1(byte[] data, int length)
    method PackAuthData (line 114) | public void PackAuthData(byte[] outdata)
    method PackData (line 140) | protected void PackData(byte[] data, ref int start, int len, byte[] ou...
    method ClientEncode (line 153) | public override byte[] ClientEncode(byte[] encryptdata, int datalength...
    method ClientDecode (line 329) | public override byte[] ClientDecode(byte[] encryptdata, int datalength...

FILE: shadowsocks-csharp/Obfs/VerifyData.cs
  class VerifyData (line 3) | public class VerifyData

FILE: shadowsocks-csharp/Obfs/VerifyDeflateObfs.cs
  class VerifyDeflateObfs (line 8) | public class VerifyDeflateObfs : VerifySimpleBase
    method VerifyDeflateObfs (line 10) | public VerifyDeflateObfs(string method)
    method SupportedObfs (line 19) | public static List<string> SupportedObfs()
    method GetObfs (line 24) | public override Dictionary<string, int[]> GetObfs()
    method PackData (line 29) | public void PackData(byte[] data, int datalength, byte[] outdata, out ...
    method ClientPreEncrypt (line 43) | public override byte[] ClientPreEncrypt(byte[] plaindata, int dataleng...
    method ClientPostDecrypt (line 76) | public override byte[] ClientPostDecrypt(byte[] plaindata, int datalen...

FILE: shadowsocks-csharp/Obfs/VerifySimpleBase.cs
  class VerifySimpleBase (line 5) | public abstract class VerifySimpleBase : ObfsBase
    method VerifySimpleBase (line 7) | public VerifySimpleBase(string method)
    method InitData (line 18) | public override object InitData()
    method LinearRandomInt (line 23) | public int LinearRandomInt(int max)
    method NonLinearRandomInt (line 28) | public int NonLinearRandomInt(int max)
    method TrapezoidRandomFloat (line 64) | public double TrapezoidRandomFloat(double d) // -1 <= d <= 1
    method TrapezoidRandomInt (line 80) | public int TrapezoidRandomInt(int max, double d)
    method ClientEncode (line 86) | public override byte[] ClientEncode(byte[] encryptdata, int datalength...
    method ClientDecode (line 92) | public override byte[] ClientDecode(byte[] encryptdata, int datalength...

FILE: shadowsocks-csharp/Obfs/xorshift128plus.cs
  class xorshift128plus (line 5) | class xorshift128plus
    method xorshift128plus (line 10) | public xorshift128plus(int init_loop_ = 4)
    method next (line 16) | public ulong next()
    method init_from_bin (line 27) | public void init_from_bin(byte[] bytes)
    method init_from_bin (line 35) | public void init_from_bin(byte[] bytes, int datalength)

FILE: shadowsocks-csharp/Program.cs
  class Program (line 18) | internal static class Program
    method Main (line 20) | [STAThread]
    method StopController (line 94) | private static void StopController()
    method App_Exit (line 101) | private static void App_Exit(object sender, ExitEventArgs e)
    method SystemEvents_PowerModeChanged (line 108) | private static void SystemEvents_PowerModeChanged(object sender, Power...
    method CurrentDomain_UnhandledException (line 147) | private static void CurrentDomain_UnhandledException(object sender, Un...
    method SendCommand (line 159) | private static void SendCommand(ISingleInstanceService service, string...
    method ArgumentsReceived (line 171) | private static void ArgumentsReceived((string, Action<string>) receive)

FILE: shadowsocks-csharp/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: shadowsocks-csharp/Proxy/CallbackState.cs
  class CallbackState (line 3) | public class CallbackState

FILE: shadowsocks-csharp/Proxy/CallbackStatus.cs
  class CallbackStatus (line 3) | class CallbackStatus
    method CallbackStatus (line 7) | public CallbackStatus()
    method SetIfEqu (line 12) | public void SetIfEqu(int newStatus, int oldStatus)

FILE: shadowsocks-csharp/Proxy/Handler.cs
  class Handler (line 22) | internal class Handler : IHandler
    type ConnectState (line 70) | enum ConnectState
    method ResetTimeout (line 92) | private void ResetTimeout(double time, bool reset_keep_alive = true)
    method timer_Elapsed (line 143) | private void timer_Elapsed(object sender, ElapsedEventArgs e)
    method setServerTransferTotal (line 212) | public void setServerTransferTotal(ServerTransferTotal transfer)
    method LogSocketException (line 217) | public int LogSocketException(Exception e)
    method ReConnect (line 339) | public bool ReConnect()
    method Start (line 379) | public void Start(byte[] firstPacket, int length, string rsp_protocol)
    method BeginConnect (line 413) | private void BeginConnect(IPAddress ipAddress, int serverPort)
    method TryReconnect (line 499) | public bool TryReconnect()
    method CloseSocket (line 524) | private void CloseSocket(ref Socket sock)
    method CloseSocket (line 553) | private void CloseSocket(ref ProxySocketTunLocal sock)
    method CloseSocket (line 582) | private void CloseSocket(ref ProxyEncryptSocket sock)
    method Shutdown (line 611) | public override void Shutdown()
    method Close (line 616) | public void Close()
    method ConnectProxyServer (line 731) | private bool ConnectProxyServer(string strRemoteHost, int iRemotePort)
    method Connect (line 757) | private void Connect()
    method ConnectCallback (line 906) | private void ConnectCallback(IAsyncResult ar)
    method doConnectionTCPRecv (line 941) | private void doConnectionTCPRecv()
    method endConnectionTCPRecv (line 952) | private int endConnectionTCPRecv(IAsyncResult ar)
    method doConnectionUDPRecv (line 963) | private void doConnectionUDPRecv()
    method endConnectionUDPRecv (line 977) | private int endConnectionUDPRecv(IAsyncResult ar, ref EndPoint endPoint)
    method doRemoteTCPRecv (line 993) | private void doRemoteTCPRecv()
    method endRemoteTCPRecv (line 1002) | private int endRemoteTCPRecv(IAsyncResult ar)
    method doRemoteUDPRecv (line 1022) | private void doRemoteUDPRecv()
    method endRemoteUDPRecv (line 1035) | private int endRemoteUDPRecv(IAsyncResult ar, ref EndPoint endPoint)
    method doConnectionRecv (line 1046) | private void doConnectionRecv()
    method SetObfsPlugin (line 1052) | private void SetObfsPlugin()
    method GetQueryString (line 1068) | private string GetQueryString()
    method GetQueryPort (line 1107) | private int GetQueryPort()
    method StartPipe (line 1149) | private void StartPipe()
    method ConnectionSend (line 1217) | private void ConnectionSend(byte[] buffer, int bytesToSend)
    method UDPoverTCPConnectionSend (line 1230) | private void UDPoverTCPConnectionSend(byte[] send_buffer, int bytesToS...
    method PipeRemoteReceiveCallback (line 1276) | private void PipeRemoteReceiveCallback(IAsyncResult ar)
    method PipeRemoteReceiveLoop (line 1358) | private void PipeRemoteReceiveLoop()
    method PipeRemoteUDPReceiveCallback (line 1448) | private void PipeRemoteUDPReceiveCallback(IAsyncResult ar)
    method RemoteSend (line 1507) | private int RemoteSend(byte[] bytes, int length)
    method RemoteSendto (line 1549) | private void RemoteSendto(byte[] bytes, int length)
    method PipeConnectionReceiveCallback (line 1556) | private void PipeConnectionReceiveCallback(IAsyncResult ar)
    method PipeConnectionUDPReceiveCallback (line 1654) | private void PipeConnectionUDPReceiveCallback(IAsyncResult ar)
    method PipeRemoteUDPSendCallback (line 1707) | private void PipeRemoteUDPSendCallback(IAsyncResult ar)
    method PipeConnectionUDPSendCallbackNoRecv (line 1724) | private void PipeConnectionUDPSendCallbackNoRecv(IAsyncResult ar)
    method PipeConnectionUDPSendCallback (line 1740) | private void PipeConnectionUDPSendCallback(IAsyncResult ar)
    method getServerUrl (line 1758) | protected string getServerUrl(out string remarks)
    method LogException (line 1770) | private void LogException(Exception e)
    method LogExceptionAndClose (line 1780) | private void LogExceptionAndClose(Exception e)

FILE: shadowsocks-csharp/Proxy/HandlerConfig.cs
  class HandlerConfig (line 6) | class HandlerConfig : ICloneable
    method Clone (line 30) | public object Clone()

FILE: shadowsocks-csharp/Proxy/HttpParser.cs
  class HttpParser (line 10) | internal class HttpParser
    method HttpParser (line 22) | public HttpParser(bool redir = false)
    method ParseHostAndPort (line 27) | private static string ParseHostAndPort(string str, ref int port)
    method ParseURL (line 62) | protected string ParseURL(string url, string host, int port)
    method HostToHandshakeBuffer (line 102) | public void HostToHandshakeBuffer(string host, int port, ref byte[] re...
    method AppendRequest (line 138) | protected int AppendRequest(ref byte[] Packet, ref int PacketLength)
    method ParseHttpHeader (line 172) | protected Dictionary<string, string> ParseHttpHeader(string header)
    method HeaderDictToString (line 191) | protected string HeaderDictToString(Dictionary<string, string> dict)
    method HandshakeReceive (line 204) | public int HandshakeReceive(byte[] _firstPacket, int _firstPacketLengt...
    method Http200 (line 296) | public static string Http200()
    method Http407 (line 301) | public static string Http407()
    method Http500 (line 316) | public static string Http500()

FILE: shadowsocks-csharp/Proxy/IHandler.cs
  class IHandler (line 3) | public abstract class IHandler
    method Shutdown (line 5) | public abstract void Shutdown();

FILE: shadowsocks-csharp/Proxy/ProxyAuthHandler.cs
  class ProxyAuthHandler (line 16) | class ProxyAuthHandler
    method ProxyAuthHandler (line 41) | public ProxyAuthHandler(Configuration config, ServerTransferTotal tran...
    method AuthConnection (line 63) | private bool AuthConnection(string authUser, string authPass)
    method HandshakeReceive (line 76) | private void HandshakeReceive()
    method RspSocks4aHandshakeReceive (line 111) | private void RspSocks4aHandshakeReceive()
    method RspSocks5HandshakeReceive (line 155) | private void RspSocks5HandshakeReceive()
    method HandshakeAuthSendCallback (line 204) | private void HandshakeAuthSendCallback(IAsyncResult ar)
    method HandshakeSendCallback (line 236) | private void HandshakeSendCallback(IAsyncResult ar)
    method HandshakeReceive2Callback (line 259) | private void HandshakeReceive2Callback(IAsyncResult ar)
    method HandshakeReceive3Callback (line 296) | private void HandshakeReceive3Callback(int bytesRemain)
    method RspSocks5UDPHeader (line 333) | private void RspSocks5UDPHeader(int bytesRead)
    method RspHttpHandshakeReceive (line 402) | private void RspHttpHandshakeReceive()
    method HttpHandshakeRecv (line 468) | private bool HttpHandshakeRecv()
    method Connect (line 491) | private void Connect()
    method CloseSocket (line 583) | private void CloseSocket(ref Socket sock)
    method Close (line 616) | private void Close()
    method Dispose (line 624) | private void Dispose()

FILE: shadowsocks-csharp/Proxy/ProxyEncryptSocket.cs
  class ProxyEncryptSocket (line 13) | class ProxyEncryptSocket
    method ProxyEncryptSocket (line 42) | public ProxyEncryptSocket(AddressFamily af, SocketType type, ProtocolT...
    method GetSocket (line 47) | public Socket GetSocket()
    method Shutdown (line 70) | public void Shutdown(SocketShutdown how)
    method Close (line 75) | public void Close()
    method BeginConnect (line 107) | public IAsyncResult BeginConnect(EndPoint ep, AsyncCallback callback, ...
    method EndConnect (line 114) | public void EndConnect(IAsyncResult ar)
    method CreateEncryptor (line 119) | public void CreateEncryptor(string method, string password)
    method SetProtocol (line 126) | public void SetProtocol(IObfs protocol)
    method SetObfs (line 131) | public void SetObfs(IObfs obfs)
    method SetObfsPlugin (line 136) | public void SetObfsPlugin(Server server, int head_len)
    method Receive (line 164) | public int Receive(byte[] recv_buffer, int size, SocketFlags flags, ou...
    method BeginReceive (line 193) | public IAsyncResult BeginReceive(byte[] buffer, int size, SocketFlags ...
    method EndReceive (line 202) | public int EndReceive(IAsyncResult ar, out bool sendback)
    method SendAll (line 236) | public int SendAll(byte[] buffer, int size, SocketFlags flags)
    method Send (line 247) | public int Send(byte[] buffer, int size, SocketFlags flags)
    method BeginReceiveFrom (line 267) | public IAsyncResult BeginReceiveFrom(byte[] buffer, int size, SocketFl...
    method RemoveRemoteUDPRecvBufferHeader (line 276) | private bool RemoveRemoteUDPRecvBufferHeader(byte[] remoteRecvBuffer, ...
    method ParseUDPHeader (line 315) | protected static byte[] ParseUDPHeader(byte[] buffer, ref int len)
    method AddRemoteUDPRecvBufferHeader (line 360) | protected void AddRemoteUDPRecvBufferHeader(byte[] decryptBuffer, byte...
    method EndReceiveFrom (line 369) | public int EndReceiveFrom(IAsyncResult ar, ref EndPoint ep)
    method BeginSendTo (line 401) | public int BeginSendTo(byte[] buffer, int size, SocketFlags flags, Asy...
    method EndSendTo (line 468) | public int EndSendTo(IAsyncResult ar)
    method GetAsyncResultSize (line 473) | public int GetAsyncResultSize(IAsyncResult ar)
    method GetAsyncProtocolSize (line 479) | public int GetAsyncProtocolSize(IAsyncResult ar)
    method GetAsyncResultBuffer (line 485) | public byte[] GetAsyncResultBuffer(IAsyncResult ar)
    method GetProxyUdpEndPoint (line 491) | public IPEndPoint GetProxyUdpEndPoint()
    method ConnectSocks5ProxyServer (line 496) | public bool ConnectSocks5ProxyServer(string strRemoteHost, int iRemote...
    method SetTcpServer (line 667) | public void SetTcpServer(string server, int port)
    method SetUdpServer (line 673) | public void SetUdpServer(string server, int port)
    method SetUdpEndPoint (line 679) | public void SetUdpEndPoint(IPEndPoint ep)
    method ConnectHttpProxyServer (line 684) | public bool ConnectHttpProxyServer(string strRemoteHost, int iRemotePo...

FILE: shadowsocks-csharp/Proxy/ProxySocketTun.cs
  class ProxySocketTun (line 10) | public class ProxySocketTun
    method ProxySocketTun (line 24) | public ProxySocketTun(Socket socket)
    method ProxySocketTun (line 29) | public ProxySocketTun(AddressFamily af, SocketType type, ProtocolType ...
    method GetSocket (line 34) | public Socket GetSocket()
    method Shutdown (line 51) | public void Shutdown(SocketShutdown how)
    method Close (line 56) | public void Close()
    method BeginConnect (line 62) | public IAsyncResult BeginConnect(EndPoint ep, AsyncCallback callback, ...
    method EndConnect (line 69) | public void EndConnect(IAsyncResult ar)
    method Receive (line 74) | public int Receive(byte[] buffer, int size, SocketFlags flags)
    method BeginReceive (line 79) | public IAsyncResult BeginReceive(byte[] buffer, int size, SocketFlags ...
    method EndReceive (line 88) | public int EndReceive(IAsyncResult ar)
    method SendAll (line 102) | public int SendAll(byte[] buffer, int size, SocketFlags flags)
    method Send (line 113) | public virtual int Send(byte[] buffer, int size, SocketFlags flags)
    method BeginSend (line 118) | public int BeginSend(byte[] buffer, int size, SocketFlags flags, Async...
    method EndSend (line 128) | public int EndSend(IAsyncResult ar)
    method BeginReceiveFrom (line 133) | public IAsyncResult BeginReceiveFrom(byte[] buffer, int size, SocketFl...
    method GetAsyncResultSize (line 142) | public int GetAsyncResultSize(IAsyncResult ar)
    method GetAsyncResultBuffer (line 148) | public byte[] GetAsyncResultBuffer(IAsyncResult ar)
    method ConnectSocks5ProxyServer (line 154) | public bool ConnectSocks5ProxyServer(string strRemoteHost, int iRemote...
    method SetTcpServer (line 322) | public void SetTcpServer(string server, int port)
    method SetUdpServer (line 328) | public void SetUdpServer(string server, int port)
    method SetUdpEndPoint (line 334) | public void SetUdpEndPoint(IPEndPoint ep)
    method ConnectHttpProxyServer (line 339) | public bool ConnectHttpProxyServer(string strRemoteHost, int iRemotePo...

FILE: shadowsocks-csharp/Proxy/ProxySocketTunLocal.cs
  class ProxySocketTunLocal (line 5) | public class ProxySocketTunLocal : ProxySocketTun
    method ProxySocketTunLocal (line 9) | public ProxySocketTunLocal(Socket socket) : base(socket)
    method Send (line 13) | public override int Send(byte[] buffer, int size, SocketFlags flags)

FILE: shadowsocks-csharp/Util/Base64.cs
  class Base64 (line 6) | public static class Base64
    method DecodeBase64 (line 8) | public static string DecodeBase64(string val)
    method DecodeBase64ToBytes (line 13) | private static byte[] DecodeBase64ToBytes(string val)
    method EncodeUrlSafeBase64 (line 19) | private static string EncodeUrlSafeBase64(byte[] val, bool trim)
    method DecodeUrlSafeBase64ToBytes (line 24) | private static byte[] DecodeUrlSafeBase64ToBytes(string val)
    method EncodeUrlSafeBase64 (line 30) | public static string EncodeUrlSafeBase64(string val, bool trim = true)
    method DecodeUrlSafeBase64 (line 35) | public static string DecodeUrlSafeBase64(string val)

FILE: shadowsocks-csharp/Util/CRC.cs
  class CRC32 (line 7) | public static class CRC32
    method CalcCRC32 (line 9) | public static ulong CalcCRC32(byte[] input, int len)
    method SetCRC32 (line 17) | public static void SetCRC32(byte[] buffer)
  class Adler32 (line 27) | public static class Adler32
    method CalcAdler32 (line 29) | public static ulong CalcAdler32(byte[] input, int len)
    method CheckAdler32 (line 43) | public static bool CheckAdler32(byte[] input, int len)

FILE: shadowsocks-csharp/Util/ColorConvert.cs
  class ColorConvert (line 8) | public static class ColorConvert
    method ColorMix (line 39) | private static byte ColorMix(byte a, byte b, double alpha)
    method ColorMix (line 44) | private static Color ColorMix(Color a, Color b, double alpha)
    method GetSpeedColor (line 51) | public static Color GetSpeedColor(long bytes)
    method GetConnectionColor (line 65) | public static Color GetConnectionColor(long connections)
    method GetLatencyColor (line 79) | public static Color GetLatencyColor(long latency)
    method GetConnectErrorColor (line 93) | public static Color GetConnectErrorColor(long val)
    method GetConnectEmptyColor (line 98) | public static Color GetConnectEmptyColor(long val)
    method GetErrorPercentColor (line 103) | public static Color GetErrorPercentColor(double? percent)

FILE: shadowsocks-csharp/Util/Constants.cs
  class Constants (line 3) | internal static class Constants

FILE: shadowsocks-csharp/Util/I18NUtil.cs
  class I18NUtil (line 8) | public static class I18NUtil
    method GetLanguage (line 27) | public static string GetLanguage(string langName = @"")
    method SetLanguage (line 41) | public static void SetLanguage(string langName)
    method GetAppStringValue (line 47) | public static string GetAppStringValue(string key)
    method GetWindowStringValue (line 56) | public static string GetWindowStringValue(this Window window, string key)
    method SetLanguage (line 65) | public static void SetLanguage(ResourceDictionary resources, string fi...
    method SetLanguage (line 80) | public static void SetLanguage(object obj)

FILE: shadowsocks-csharp/Util/JsonUtils.cs
  class JsonUtils (line 6) | public static class JsonUtils
    method Serialize (line 20) | public static string Serialize(object obj, bool strict)

FILE: shadowsocks-csharp/Util/NetUtils/DnsUtil.cs
  class DnsUtil (line 13) | public static class DnsUtil
    method QueryDns (line 17) | public static IPAddress? QueryDns(string host)
    method QueryDefaultAsync (line 28) | public static async Task<IPAddress?> QueryDefaultAsync(string host, bo...
    method QueryAsync (line 33) | public static async Task<IPAddress?> QueryAsync(string host, IEnumerab...

FILE: shadowsocks-csharp/Util/NetUtils/IPSubnet.cs
  class IPSubnet (line 9) | public static class IPSubnet
    method IsInSubnet (line 11) | public static bool IsInSubnet(this IPAddress address, string subnetMask)
    method IsLoopBack (line 77) | public static bool IsLoopBack(IPAddress ip)
    method IsLocal (line 82) | public static bool IsLocal(IPAddress ip)
    method IsLocal (line 87) | public static bool IsLocal(Socket socket)
    method IsLan (line 92) | public static bool IsLan(IPAddress ip)
    method IsLan (line 116) | public static bool IsLan(Socket socket)

FILE: shadowsocks-csharp/Util/NetUtils/SocketUtil.cs
  class SocketUtil (line 6) | public static class SocketUtil
    method FullClose (line 8) | public static void FullClose(this Socket s)

FILE: shadowsocks-csharp/Util/NetUtils/WrappedSocket.cs
  class WrappedSocket (line 17) | public class WrappedSocket
    method BeginConnect (line 29) | public void BeginConnect(EndPoint remoteEP, AsyncCallback callback, ob...
    class FakeAsyncResult (line 50) | private class FakeAsyncResult : IAsyncResult
    class TcpUserToken (line 60) | private class TcpUserToken
      method TcpUserToken (line 65) | public TcpUserToken(AsyncCallback callback, object state)
    method OnTcpConnectCompleted (line 72) | private void OnTcpConnectCompleted(object sender, SocketAsyncEventArgs...
    method EndConnect (line 130) | public void EndConnect(IAsyncResult asyncResult)
    method Dispose (line 149) | public void Dispose()
    method BeginSend (line 175) | public IAsyncResult BeginSend(byte[] buffer, int offset, int size, Soc...
    method EndSend (line 189) | public int EndSend(IAsyncResult asyncResult)
    method BeginReceive (line 203) | public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, ...
    method EndReceive (line 217) | public int EndReceive(IAsyncResult asyncResult)
    method Shutdown (line 231) | public void Shutdown(SocketShutdown how)
    method SetSocketOption (line 245) | public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptio...
    method SetSocketOption (line 250) | public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptio...

FILE: shadowsocks-csharp/Util/QrCodeUtils.cs
  class QrCodeUtils (line 16) | public static class QrCodeUtils
    method ToBitmapImage (line 18) | private static BitmapImage ToBitmapImage(Image src)
    method GenQrCode (line 30) | public static ImageSource GenQrCode(string content, int width, int hei...
    method GenQrCode2 (line 50) | public static ImageSource GenQrCode2(string str, int height)
    method ScanBitmap (line 82) | public static Result ScanBitmap(Bitmap target)

FILE: shadowsocks-csharp/Util/RNG.cs
  class Rng (line 6) | public static class Rng
    method RandBytes (line 8) | public static void RandBytes(byte[] buf, int length = -1)

FILE: shadowsocks-csharp/Util/Reg.cs
  class Reg (line 6) | public static class Reg
    method SetUrlProtocol (line 8) | [Conditional("RELEASE")]
    method RemoveUrlProtocol (line 22) | [Conditional("RELEASE")]

FILE: shadowsocks-csharp/Util/Utils.cs
  class Utils (line 17) | public static class Utils
    method SetArrayMinSize (line 19) | public static void SetArrayMinSize<T>(ref T[] array, int size)
    method SetArrayMinSize2 (line 27) | public static void SetArrayMinSize2<T>(ref T[] array, int size)
    method GetExecutablePath (line 35) | public static string GetExecutablePath()
    method GetDllPath (line 48) | public static string GetDllPath()
    method GetTempPath (line 70) | public static string GetTempPath(string filename)
    method IsGFWListPAC (line 75) | public static bool IsGFWListPAC(string filename)
    method OpenURL (line 89) | public static void OpenURL(string path)
    method EncryptLargeBytesToBase64String (line 100) | public static string EncryptLargeBytesToBase64String(IEncryptor encryp...
    method DecryptLargeBase64StringToBytes (line 119) | public static byte[] DecryptLargeBase64StringToBytes(IEncryptor encryp...
    method FormatBytes (line 140) | public static string FormatBytes(long bytes)
    method Except (line 169) | public static IEnumerable<Server> Except(this IEnumerable<Server> x, I...
    method GetLines (line 174) | public static IEnumerable<string> GetLines(this string str, bool remov...
    method SetTls (line 188) | public static void SetTls()

FILE: shadowsocks-csharp/Util/ViewUtils.cs
  class ViewUtils (line 16) | public static class ViewUtils
    method DestroyIcon (line 22) | [DllImport(@"user32.dll", CharSet = CharSet.Auto)]
    method BringToFront (line 25) | public static void BringToFront(this FrameworkElement element)
    method FindVisualChildren (line 37) | public static IEnumerable<T> FindVisualChildren<T>(DependencyObject de...
    method SelectColorMask (line 57) | public static Color SelectColorMask(bool isProxyEnabled, bool isGlobal...
    method ChangeBitmapColor (line 67) | public static Bitmap ChangeBitmapColor(Bitmap original, Color colorMas...
    method ResizeBitmap (line 93) | public static Bitmap ResizeBitmap(Bitmap original, int width, int height)
    method GetDpi (line 107) | public static int GetDpi()
    method GetIconSize (line 118) | public static Size GetIconSize()
    method SetResource (line 132) | public static void SetResource(ResourceDictionary resources, string fi...
    method IsOnScreen (line 145) | public static bool IsOnScreen(Window window)
    method IsOnScreen (line 151) | public static bool IsOnScreen(double x, double y)
    method IsScrolledToEnd (line 160) | public static bool IsScrolledToEnd(this TextBox textBox)

FILE: shadowsocks-csharp/View/Controls/BindablePasswordBox.cs
  class BindablePasswordBox (line 6) | public sealed class BindablePasswordBox : Decorator
    method BindablePasswordBox (line 19) | static BindablePasswordBox()
    method BindablePasswordBox (line 32) | public BindablePasswordBox()
    method OnPasswordPropertyChanged (line 55) | private static void OnPasswordPropertyChanged(DependencyObject d, Depe...
    method HandlePasswordChanged (line 75) | private void HandlePasswordChanged(object sender, RoutedEventArgs even...

FILE: shadowsocks-csharp/View/Controls/GridColumnSizerExt.cs
  class GridColumnSizerExt (line 7) | public class GridColumnSizerExt : GridColumnSizer
    method GridColumnSizerExt (line 9) | public GridColumnSizerExt(SfDataGrid dataGrid) : base(dataGrid) { }
    method CalculateCellWidth (line 11) | protected override double CalculateCellWidth(GridColumn column, bool s...

FILE: shadowsocks-csharp/View/Controls/MaskedTextBox.xaml.cs
  class MaskedTextBox (line 6) | public partial class MaskedTextBox
    method MaskedTextBox (line 8) | public MaskedTextBox()
    method MaskedTextBoxPlainModeChanged (line 52) | private void MaskedTextBoxPlainModeChanged(object sender, EventArgs e)

FILE: shadowsocks-csharp/View/Controls/NumberUpDown.xaml.cs
  class NumberUpDown (line 7) | public partial class NumberUpDown
    method NumberUpDown (line 62) | public NumberUpDown()
    method Up_Click (line 67) | private void Up_Click(object sender, RoutedEventArgs e)
    method Down_Click (line 79) | private void Down_Click(object sender, RoutedEventArgs e)
    method TxtNum_TextChanged (line 91) | private void TxtNum_TextChanged(object sender, TextChangedEventArgs e)
    method UserControl_Loaded (line 104) | private void UserControl_Loaded(object sender, RoutedEventArgs e)
    method Grid_LostFocus (line 109) | private void Grid_LostFocus(object sender, RoutedEventArgs e)

FILE: shadowsocks-csharp/View/DnsSettingWindow.xaml.cs
  class DnsSettingWindow (line 9) | public partial class DnsSettingWindow
    method DnsSettingWindow (line 11) | public DnsSettingWindow()
    method DnsSettingViewModel_DnsClientsChanged (line 23) | private void DnsSettingViewModel_DnsClientsChanged(object sender, Syst...
    method LoadConfig (line 30) | private void LoadConfig()
    method SaveConfig (line 36) | private void SaveConfig()
    method AddButton_OnClick (line 44) | private void AddButton_OnClick(object sender, RoutedEventArgs e)
    method DeleteButton_OnClick (line 49) | private void DeleteButton_OnClick(object sender, RoutedEventArgs e)
    method OkButton_OnClick (line 54) | private void OkButton_OnClick(object sender, RoutedEventArgs e)
    method CancelButton_OnClick (line 60) | private void CancelButton_OnClick(object sender, RoutedEventArgs e)
    method ApplyButton_OnClick (line 65) | private void ApplyButton_OnClick(object sender, RoutedEventArgs e)
    method TestButton_OnClick (line 71) | private void TestButton_OnClick(object sender, RoutedEventArgs e)

FILE: shadowsocks-csharp/View/LogWindow.xaml.cs
  class LogWindow (line 13) | public partial class LogWindow
    method LogWindow (line 15) | public LogWindow()
    method ReadLog (line 29) | private void ReadLog()
    method ClearLogMenuItem_Click (line 90) | private void ClearLogMenuItem_Click(object sender, RoutedEventArgs e)
    method ShowInExplorerMenuItem_Click (line 97) | private void ShowInExplorerMenuItem_Click(object sender, RoutedEventAr...
    method Window_Loaded (line 110) | private void Window_Loaded(object sender, RoutedEventArgs e)
    method SyncLog (line 115) | private async void SyncLog(CancellationTokenSource cts)
    method CloseMenuItem_Click (line 135) | private void CloseMenuItem_Click(object sender, RoutedEventArgs e)
    method FontMenuItem_Click (line 140) | private void FontMenuItem_Click(object sender, RoutedEventArgs e)
    method WrapTextMenuItem_Click (line 157) | private void WrapTextMenuItem_Click(object sender, RoutedEventArgs e)
    method AlwaysOnTopMenuItem_Click (line 162) | private void AlwaysOnTopMenuItem_Click(object sender, RoutedEventArgs e)
    method WrapTextMenuItem_Checked (line 167) | private void WrapTextMenuItem_Checked(object sender, RoutedEventArgs e)
    method AlwaysOnTopMenuItem_Checked (line 173) | private void AlwaysOnTopMenuItem_Checked(object sender, RoutedEventArg...
    method Window_Closed (line 178) | private void Window_Closed(object sender, EventArgs e)

FILE: shadowsocks-csharp/View/PortSettingsWindow.xaml.cs
  class PortSettingsWindow (line 14) | public partial class PortSettingsWindow
    method PortSettingsWindow (line 22) | public PortSettingsWindow(MainController controller)
    method Window_Loaded (line 31) | private void Window_Loaded(object sender, RoutedEventArgs _)
    method PortSettingsWindow_ValueChanged (line 77) | private void PortSettingsWindow_ValueChanged(object sender, EventArgs e)
    method LoadItems (line 82) | private void LoadItems()
    method controller_ConfigChanged (line 93) | private void controller_ConfigChanged(object sender, EventArgs e)
    method LoadCurrentConfiguration (line 99) | private void LoadCurrentConfiguration()
    method LoadConfiguration (line 106) | private void LoadConfiguration(Configuration configuration)
    method SaveSelectedServer (line 149) | private void SaveSelectedServer()
    method GetIdText (line 191) | private string GetIdText(string id)
    method LoadSelectedServer (line 204) | private void LoadSelectedServer()
    method AddButton_Click (line 239) | private void AddButton_Click(object sender, RoutedEventArgs e)
    method DeleteButton_Click (line 275) | private void DeleteButton_Click(object sender, RoutedEventArgs e)
    method TypeComboBox_SelectionChanged (line 288) | private void TypeComboBox_SelectionChanged(object sender, SelectionCha...
    method PortsListBox_SelectionChanged (line 302) | private void PortsListBox_SelectionChanged(object sender, SelectionCha...
    method SaveConfig (line 323) | private void SaveConfig()
    method OkButton_Click (line 329) | private void OkButton_Click(object sender, RoutedEventArgs e)
    method CancelButton_Click (line 338) | private void CancelButton_Click(object sender, RoutedEventArgs e)
    method ApplyButton_Click (line 343) | private void ApplyButton_Click(object sender, RoutedEventArgs e)
    method GetDisplayText (line 351) | private static string GetDisplayText(Server s)
    method GetId (line 356) | private static string GetId(string text)
    method ServerListText2Key (line 366) | private static string ServerListText2Key(string text)

FILE: shadowsocks-csharp/View/QRCodeSplashWindow.xaml.cs
  class QRCodeSplashWindow (line 9) | public partial class QRCodeSplashWindow
    method QRCodeSplashWindow (line 11) | public QRCodeSplashWindow()
    method Window_Loaded (line 28) | private void Window_Loaded(object sender, RoutedEventArgs e)
    method Splash (line 39) | private async void Splash()

FILE: shadowsocks-csharp/View/ServerConfigWindow.xaml.cs
  class ServerConfigWindow (line 18) | public partial class ServerConfigWindow
    method ServerConfigWindow (line 20) | public ServerConfigWindow(MainController controller, int focusIndex)
    method ServerViewModel_ServersChanged (line 52) | private void ServerViewModel_ServersChanged(object sender, EventArgs e)
    method Window_Loaded (line 89) | private void Window_Loaded(object sender, RoutedEventArgs e)
    method UpdateTitle (line 125) | private void UpdateTitle()
    method controller_ConfigChanged (line 130) | private void controller_ConfigChanged(object sender, EventArgs e)
    method LoadCurrentConfiguration (line 136) | private void LoadCurrentConfiguration(bool scrollToSelectedItem)
    method MoveToSelectedItem (line 154) | public void MoveToSelectedItem(int index)
    method MoveToSelectedItem (line 163) | private void MoveToSelectedItem(string id)
    method MoveToSelectedItem (line 172) | private void MoveToSelectedItem(ServerTreeViewModel serverTreeViewModel)
    method AddButton_Click (line 180) | private void AddButton_Click(object sender, RoutedEventArgs e)
    method DeleteButton_Click (line 225) | private void DeleteButton_Click(object sender, RoutedEventArgs e)
    method ServersTreeView_OnSelectionChanged (line 239) | private void ServersTreeView_OnSelectionChanged(object sender, ItemSel...
    method ServersTreeView_OnItemDropping (line 253) | private void ServersTreeView_OnItemDropping(object sender, TreeViewIte...
    method LinkTextBox_TextChanged (line 362) | private void LinkTextBox_TextChanged(object sender, TextChangedEventAr...
    method LinkTextBox_PreviewMouseUp (line 367) | private void LinkTextBox_PreviewMouseUp(object sender, MouseButtonEven...
    method LinkTextBox_GotFocus (line 376) | private void LinkTextBox_GotFocus(object sender, RoutedEventArgs e)
    method ObfsComboBox_SelectionChanged (line 383) | private void ObfsComboBox_SelectionChanged(object sender, SelectionCha...
    method SaveConfig (line 401) | private bool SaveConfig()
    method OkButton_Click (line 429) | private void OkButton_Click(object sender, RoutedEventArgs e)
    method CancelButton_Click (line 444) | private void CancelButton_Click(object sender, RoutedEventArgs e)
    method ApplyButton_Click (line 449) | private void ApplyButton_Click(object sender, RoutedEventArgs e)
    method GenQr (line 459) | private void GenQr(string text)
    method ShowQrCodeButton_OnClick (line 488) | private void ShowQrCodeButton_OnClick(object sender, RoutedEventArgs e)
    method ConfigWindow_OnActivated (line 509) | private void ConfigWindow_OnActivated(object sender, EventArgs e)

FILE: shadowsocks-csharp/View/ServerLogWindow.xaml.cs
  class ServerLogWindow (line 20) | public partial class ServerLogWindow
    method ServerLogWindow (line 22) | public ServerLogWindow(MainController controller, WindowStatus status)
    method LoadLanguage (line 51) | private void LoadLanguage()
    method LoadConfig (line 72) | private void LoadConfig(bool isFirstLoad)
    method controller_ConfigChanged (line 88) | private void controller_ConfigChanged(object sender, EventArgs e)
    method UpdateTitle (line 96) | private void UpdateTitle()
    method AlwaysTopMenuItem_OnClick (line 101) | private void AlwaysTopMenuItem_OnClick(object sender, RoutedEventArgs e)
    method AutoSizeMenuItem_OnClick (line 106) | private void AutoSizeMenuItem_OnClick(object sender, RoutedEventArgs e)
    method DisconnectDirectMenuItem_OnClick (line 119) | private void DisconnectDirectMenuItem_OnClick(object sender, RoutedEve...
    method DisconnectAllMenuItem_OnClick (line 124) | private void DisconnectAllMenuItem_OnClick(object sender, RoutedEventA...
    method ClearMaxMenuItem_OnClick (line 130) | private void ClearMaxMenuItem_OnClick(object sender, RoutedEventArgs e)
    method ClearAllMenuItem_OnClick (line 139) | private void ClearAllMenuItem_OnClick(object sender, RoutedEventArgs e)
    method ClearSelectedTotalMenuItem_OnClick (line 148) | private void ClearSelectedTotalMenuItem_OnClick(object sender, RoutedE...
    method ClearTotalMenuItem_OnClick (line 164) | private void ClearTotalMenuItem_OnClick(object sender, RoutedEventArgs e)
    method CopyCurrentLinkMenuItem_OnClick (line 173) | private void CopyCurrentLinkMenuItem_OnClick(object sender, RoutedEven...
    method CopyCurrentGroupLinksMenuItem_OnClick (line 183) | private void CopyCurrentGroupLinksMenuItem_OnClick(object sender, Rout...
    method CopyAllEnableLinksMenuItem_OnClick (line 194) | private void CopyAllEnableLinksMenuItem_OnClick(object sender, RoutedE...
    method CopyAllLinksMenuItem_OnClick (line 201) | private void CopyAllLinksMenuItem_OnClick(object sender, RoutedEventAr...
    method ServerDataGrid_OnCellTapped (line 208) | private void ServerDataGrid_OnCellTapped(object sender, GridCellTapped...
    method ServerDataGrid_OnCellDoubleTapped (line 249) | private void ServerDataGrid_OnCellDoubleTapped(object sender, GridCell...
    method ServerDataGrid_OnMouseLeftButtonUp (line 300) | private void ServerDataGrid_OnMouseLeftButtonUp(object sender, MouseBu...

FILE: shadowsocks-csharp/View/SettingsWindow.xaml.cs
  class SettingsWindow (line 11) | public partial class SettingsWindow
    method SettingsWindow (line 13) | public SettingsWindow(MainController controller)
    method LoadCurrentConfiguration (line 27) | private void LoadCurrentConfiguration()
    method controller_ConfigChanged (line 39) | private void controller_ConfigChanged(object sender, EventArgs e)
    method SaveConfig (line 44) | private void SaveConfig()
    method OkButton_Click (line 59) | private void OkButton_Click(object sender, RoutedEventArgs e)
    method CancelButton_Click (line 68) | private void CancelButton_Click(object sender, RoutedEventArgs e)
    method ApplyButton_Click (line 73) | private void ApplyButton_Click(object sender, RoutedEventArgs e)
    method DefaultButton_Click (line 78) | private void DefaultButton_Click(object sender, RoutedEventArgs e)
    method AutoStartupCheckBox_CheckedChanged (line 85) | private void AutoStartupCheckBox_CheckedChanged(object sender, RoutedE...

FILE: shadowsocks-csharp/View/ShowTextWindow.xaml.cs
  class ShowTextWindow (line 7) | public partial class ShowTextWindow
    method ShowTextWindow (line 9) | public ShowTextWindow(string text)
    method TextBox_TextChanged (line 16) | private void TextBox_TextChanged(object sender, System.Windows.Control...
    method ShowTextWindow_SizeChanged (line 21) | private void ShowTextWindow_SizeChanged(object sender, SizeChangedEven...
    method ShowTextWindow_Loaded (line 28) | private void ShowTextWindow_Loaded(object sender, RoutedEventArgs e)
    method GenQr (line 36) | private void GenQr(string text)

FILE: shadowsocks-csharp/View/SubscribeWindow.xaml.cs
  class SubscribeWindow (line 13) | public partial class SubscribeWindow
    method SubscribeWindow (line 15) | public SubscribeWindow(MainController controller)
    method SubscribeWindowViewModel_SubscribesChanged (line 30) | private void SubscribeWindowViewModel_SubscribesChanged(object sender,...
    method Window_Loaded (line 42) | private void Window_Loaded(object sender, RoutedEventArgs _)
    method controller_ConfigChanged (line 47) | private void controller_ConfigChanged(object sender, EventArgs e)
    method LoadCurrentConfiguration (line 52) | private void LoadCurrentConfiguration()
    method ServerSubscribeListBox_SelectionChanged (line 60) | private void ServerSubscribeListBox_SelectionChanged(object sender, Se...
    method DeleteUnusedServer (line 65) | private void DeleteUnusedServer()
    method SaveConfig (line 73) | private bool SaveConfig()
    method OkButton_Click (line 102) | private void OkButton_Click(object sender, RoutedEventArgs e)
    method CancelButton_Click (line 115) | private void CancelButton_Click(object sender, RoutedEventArgs e)
    method ApplyButton_Click (line 120) | private void ApplyButton_Click(object sender, RoutedEventArgs e)
    method AddButton_Click (line 129) | private void AddButton_Click(object sender, RoutedEventArgs e)
    method DeleteButton_Click (line 135) | private void DeleteButton_Click(object sender, RoutedEventArgs e)
    method SetServerListSelectedIndex (line 149) | private void SetServerListSelectedIndex(int index)
    method Save (line 171) | private bool Save()
    method SaveError (line 176) | private void SaveError()
    method UpdateButton_OnClick (line 181) | private void UpdateButton_OnClick(object sender, RoutedEventArgs e)

FILE: shadowsocks-csharp/View/ValueConverter/BalanceTypeEnumConverter.cs
  class BalanceTypeEnumConverter (line 10) | public class BalanceTypeEnumConverter : IValueConverter
    method Convert (line 12) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 22) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/BooleanToEnabledConverter.cs
  class BooleanToEnabledConverter (line 10) | public class BooleanToEnabledConverter : IValueConverter
    method Convert (line 12) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 31) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/ConnectEmptyToBrushConverter.cs
  class ConnectEmptyToBrushConverter (line 9) | public class ConnectEmptyToBrushConverter : IValueConverter
    method Convert (line 11) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 21) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/ConnectErrorToBrushConverter.cs
  class ConnectErrorToBrushConverter (line 9) | public class ConnectErrorToBrushConverter : IValueConverter
    method Convert (line 11) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 21) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/ConnectNumberToBrushConverter.cs
  class ConnectNumberToBrushConverter (line 9) | public class ConnectNumberToBrushConverter : IValueConverter
    method Convert (line 11) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 21) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/ErrorPercentToBrushConverter.cs
  class ErrorPercentToBrushConverter (line 9) | public class ErrorPercentToBrushConverter : IValueConverter
    method Convert (line 11) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 21) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/LatencyToBrushConverter.cs
  class LatencyToBrushConverter (line 9) | public class LatencyToBrushConverter : IValueConverter
    method Convert (line 11) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 21) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/ProxyTypeConverter.cs
  class ProxyTypeConverter (line 7) | public class ProxyTypeConverter : IValueConverter
    method Convert (line 9) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 14) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/ProxyTypeEnumConverter.cs
  class ProxyTypeEnumConverter (line 10) | public class ProxyTypeEnumConverter : IValueConverter
    method Convert (line 12) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 21) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/ServerTreeTypeToFontConverter.cs
  class ServerTreeTypeToFontConverter (line 10) | public class ServerTreeTypeToFontConverter : IValueConverter
    method Convert (line 12) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 45) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/SpeedToBrushConverter.cs
  class SpeedToBrushConverter (line 9) | public class SpeedToBrushConverter : IValueConverter
    method Convert (line 11) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 20) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/TotalDownloadBackgroundBrushConvert.cs
  class TotalDownloadBackgroundBrushConvert (line 10) | public class TotalDownloadBackgroundBrushConvert : IValueConverter
    method Convert (line 12) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 24) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/TotalDownloadRawBackgroundBrushConvert.cs
  class TotalDownloadRawBackgroundBrushConvert (line 10) | public class TotalDownloadRawBackgroundBrushConvert : IValueConverter
    method Convert (line 12) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 24) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/TotalUploadBackgroundBrushConvert.cs
  class TotalUploadBackgroundBrushConvert (line 10) | public class TotalUploadBackgroundBrushConvert : IValueConverter
    method Convert (line 12) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 24) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/View/ValueConverter/UnixSecondsToString.cs
  class UnixSecondsToString (line 6) | public class UnixSecondsToString : IValueConverter
    method Convert (line 8) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 20) | public object ConvertBack(object value, Type targetType, object parame...

FILE: shadowsocks-csharp/ViewModel/DnsSettingViewModel.cs
  class DnsSettingViewModel (line 11) | public class DnsSettingViewModel : ViewModelBase
    method DnsSettingViewModel (line 13) | public DnsSettingViewModel()
    method CurrentClient_PropertyChanged (line 23) | private void CurrentClient_PropertyChanged(object sender, System.Compo...
    method Clients_CollectionChanged (line 46) | private void Clients_CollectionChanged(object sender, System.Collectio...
    method ReadConfig (line 87) | public void ReadConfig()
    method SaveConfig (line 100) | public void SaveConfig()
    method AddNewDns (line 111) | public void AddNewDns()
    method Delete (line 118) | public void Delete()

FILE: shadowsocks-csharp/ViewModel/ServerConfigViewModel.cs
  class ServerConfigViewModel (line 10) | public class ServerConfigViewModel : ViewModelBase
    method ServerConfigViewModel (line 12) | public ServerConfigViewModel()
    method ReadServers (line 30) | public void ReadServers(List<Server> configs)
    method ServerTreeViewModelToList (line 84) | public static IEnumerable<Server> ServerTreeViewModelToList(IEnumerabl...
    method ServerCollection_CollectionChanged (line 101) | private void ServerCollection_CollectionChanged(object sender, System....
    method ServerChanged (line 108) | private void ServerChanged(object sender, EventArgs e)

FILE: shadowsocks-csharp/ViewModel/ServerLogViewModel.cs
  class ServerLogViewModel (line 6) | public class ServerLogViewModel : ViewModelBase
    method ServerLogViewModel (line 8) | public ServerLogViewModel()
    method ReadConfig (line 27) | public void ReadConfig()

FILE: shadowsocks-csharp/ViewModel/SettingViewModel.cs
  class SettingViewModel (line 5) | public class SettingViewModel : ViewModelBase
    method SettingViewModel (line 7) | public SettingViewModel()
    method ReadConfig (line 20) | public void ReadConfig()

FILE: shadowsocks-csharp/ViewModel/SubscribeWindowViewModel.cs
  class SubscribeWindowViewModel (line 7) | public class SubscribeWindowViewModel : ViewModelBase
    method SubscribeWindowViewModel (line 9) | public SubscribeWindowViewModel()
    method ReadConfig (line 14) | public void ReadConfig(Configuration config)
    method SubscribeCollection_CollectionChanged (line 26) | private void SubscribeCollection_CollectionChanged(object sender, Syst...
    method _selectedServer_SubscribeChanged (line 63) | private void _selectedServer_SubscribeChanged(object sender, EventArgs e)

FILE: shadowsocks-csharp/ViewModel/ViewModelBase.cs
  class ViewModelBase (line 7) | public abstract class ViewModelBase : INotifyPropertyChanged
    method OnPropertyChanged (line 11) | protected void OnPropertyChanged(string propertyName) => PropertyChang...
    method SetField (line 13) | protected virtual bool SetField<T>(ref T field, T value, [CallerMember...
Condensed preview — 223 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,457K chars).
[
  {
    "path": ".editorconfig",
    "chars": 8163,
    "preview": "# 如果要从更高级别的目录继承 .editorconfig 设置,请删除以下行\nroot = true\n\n[*]\n# 字符集\ncharset = utf-8\n\n# 缩进和间距\nindent_style = space\nindent_size"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 402,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"[BUG]\"\nlabels: Bug\nassignees: ''\n\n---\n\n**描述 bug**"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 140,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Telegram Channel\n    url: https://t.me/ShadowsocksR_Windows\n    abo"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 269,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: Enhancement\nassignees: ''\n\n---\n\n**您的"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/other-issue.md",
    "chars": 533,
    "preview": "---\nname: Other issue\nabout: Other issue\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n之所以写中文,本issue是写给打算写给乱发中文问题的人看的\n\n1. 不欢迎"
  },
  {
    "path": ".github/renovate.json",
    "chars": 431,
    "preview": "{\n\t\"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n\t\"assignees\": [\n\t\t\"HMBSbige\"\n\t],\n\t\"commitMessagePrefi"
  },
  {
    "path": ".github/workflows/CI.yml",
    "chars": 4902,
    "preview": "name: CI\non: [push, pull_request, workflow_dispatch]\nenv:\n  ProjectName: ShadowsocksR\n\njobs:\n\n  build:\n    name: Build\n "
  },
  {
    "path": ".gitignore",
    "chars": 5958,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
  },
  {
    "path": "Build/DotNetDllPathPatcher.ps1",
    "chars": 2191,
    "preview": "using namespace System.IO\nusing namespace System.Text\n\nparam([string]$exe_path, [string]$target_path = 'bin')\n$ErrorActi"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 177,
    "preview": "How to Contribute\n=================\n\nPull Requests\n-------------\n\n1. Pull requests are welcome.\n2. Make sure to pass the"
  },
  {
    "path": "LICENSE",
    "chars": 35817,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\r\n                       Version 3, 29 June 2007\r\n\r\n Copyright (C) 2007 Fr"
  },
  {
    "path": "README.md",
    "chars": 823,
    "preview": "<img src=\"shadowsocks-csharp/Resources/ssw128.png\" width=\"48\"/>ShadowsocksR for Windows\n=======================\n\n[![](ht"
  },
  {
    "path": "UnitTest/DnsTest.cs",
    "chars": 3440,
    "preview": "using Microsoft.VisualStudio.TestTools.UnitTesting;\nusing Shadowsocks.Enums;\nusing Shadowsocks.Util.NetUtils;\nusing Syst"
  },
  {
    "path": "UnitTest/EncryptionTest.cs",
    "chars": 4635,
    "preview": "using Microsoft.VisualStudio.TestTools.UnitTesting;\nusing Shadowsocks.Encryption;\nusing Shadowsocks.Encryption.Stream;\nu"
  },
  {
    "path": "UnitTest/IPSubnet.cs",
    "chars": 3258,
    "preview": "using Microsoft.VisualStudio.TestTools.UnitTesting;\nusing Shadowsocks.Util.NetUtils;\nusing System.Net;\n\nnamespace UnitTe"
  },
  {
    "path": "UnitTest/ServerTest.cs",
    "chars": 2428,
    "preview": "using Microsoft.VisualStudio.TestTools.UnitTesting;\nusing Shadowsocks.Model;\nusing System;\n\nnamespace UnitTest\n{\n    [Te"
  },
  {
    "path": "UnitTest/SubscribeTest.cs",
    "chars": 818,
    "preview": "using Microsoft.VisualStudio.TestTools.UnitTesting;\nusing Shadowsocks.Controller.HttpRequest;\nusing Shadowsocks.Util;\nus"
  },
  {
    "path": "UnitTest/UnitTest.cs",
    "chars": 1140,
    "preview": "using Microsoft.VisualStudio.TestTools.UnitTesting;\nusing Shadowsocks.Encryption;\nusing Shadowsocks.Util;\nusing System.L"
  },
  {
    "path": "UnitTest/UnitTest.csproj",
    "chars": 566,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net7.0-windows</TargetFramework>\n    <LangVers"
  },
  {
    "path": "build.ps1",
    "chars": 1544,
    "preview": "param([string]$buildtfm = 'all')\n$ErrorActionPreference = 'Stop'\n\nWrite-Host 'dotnet SDK info'\ndotnet --info\n\n$exe = 'Sh"
  },
  {
    "path": "shadowsocks-csharp/Controller/AutoStartup.cs",
    "chars": 1358,
    "preview": "using CryptoBase;\r\nusing RunAtStartup;\r\nusing System;\r\nusing System.IO;\r\nusing Utils = Shadowsocks.Util.Utils;\r\n\r\nnamesp"
  },
  {
    "path": "shadowsocks-csharp/Controller/FileManager.cs",
    "chars": 5168,
    "preview": "using System;\nusing System.Diagnostics.CodeAnalysis;\nusing System.IO;\nusing System.IO.Compression;\nusing System.Text;\nus"
  },
  {
    "path": "shadowsocks-csharp/Controller/HttpRequest/GfwListUpdater.cs",
    "chars": 4934,
    "preview": "using Shadowsocks.Controller.Service;\nusing Shadowsocks.Enums;\nusing Shadowsocks.Model;\nusing Shadowsocks.Properties;\nus"
  },
  {
    "path": "shadowsocks-csharp/Controller/HttpRequest/HttpRequest.cs",
    "chars": 4090,
    "preview": "using Shadowsocks.Model;\nusing System;\nusing System.Net;\nusing System.Net.Http;\nusing System.Threading.Tasks;\n\nnamespace"
  },
  {
    "path": "shadowsocks-csharp/Controller/HttpRequest/UpdateChecker.cs",
    "chars": 2329,
    "preview": "using Shadowsocks.Model;\nusing System;\nusing UpdateChecker;\n\nnamespace Shadowsocks.Controller.HttpRequest\n{\n    public c"
  },
  {
    "path": "shadowsocks-csharp/Controller/HttpRequest/UpdateNode.cs",
    "chars": 2040,
    "preview": "using Shadowsocks.Enums;\nusing Shadowsocks.Model;\nusing System;\nusing System.Net;\n\nnamespace Shadowsocks.Controller.Http"
  },
  {
    "path": "shadowsocks-csharp/Controller/Logging.cs",
    "chars": 9603,
    "preview": "using Shadowsocks.Enums;\r\nusing Shadowsocks.Obfs;\r\nusing Shadowsocks.Util;\r\nusing System;\r\nusing System.Collections.Gene"
  },
  {
    "path": "shadowsocks-csharp/Controller/MainController.cs",
    "chars": 19198,
    "preview": "using Shadowsocks.Controller.HttpRequest;\nusing Shadowsocks.Controller.Service;\nusing Shadowsocks.Enums;\nusing Shadowsoc"
  },
  {
    "path": "shadowsocks-csharp/Controller/MenuViewController.cs",
    "chars": 55077,
    "preview": "using Hardcodet.Wpf.TaskbarNotification;\nusing Microsoft.Win32;\nusing Shadowsocks.Controller.HttpRequest;\nusing Shadowso"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/HostDaemon.cs",
    "chars": 3071,
    "preview": "using Shadowsocks.Model;\nusing System;\nusing System.IO;\nusing System.Threading.Tasks;\n\nnamespace Shadowsocks.Controller."
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/HostMap.cs",
    "chars": 3916,
    "preview": "using Shadowsocks.Model;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Net;\n\nnamespace S"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/HttpPortForwarder.cs",
    "chars": 12394,
    "preview": "using Shadowsocks.Model;\nusing Shadowsocks.Proxy;\nusing Shadowsocks.Util.NetUtils;\nusing System;\nusing System.Net;\nusing"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/HttpProxyRunner.cs",
    "chars": 1395,
    "preview": "using HttpProxy;\nusing Microsoft.VisualStudio.Threading;\nusing Shadowsocks.Model;\nusing Socks5.Models;\nusing System.Net;"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/Listener.cs",
    "chars": 7492,
    "preview": "using Shadowsocks.Enums;\nusing Shadowsocks.Model;\nusing Shadowsocks.Util;\nusing Shadowsocks.Util.NetUtils;\nusing System;"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/Local.cs",
    "chars": 1913,
    "preview": "using Shadowsocks.Model;\nusing Shadowsocks.Model.Transfer;\nusing Shadowsocks.Proxy;\nusing System.Diagnostics;\nusing Syst"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/PACDaemon.cs",
    "chars": 4483,
    "preview": "using Shadowsocks.Properties;\nusing System;\nusing System.IO;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/PACServer.cs",
    "chars": 7939,
    "preview": "using Shadowsocks.Enums;\nusing Shadowsocks.Model;\nusing Shadowsocks.Util;\nusing System;\nusing System.Net;\nusing System.N"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/ProtocolResponseDetector.cs",
    "chars": 3944,
    "preview": "using System;\n\nnamespace Shadowsocks.Controller.Service\n{\n    internal class ProtocolResponseDetector\n    {\n        prot"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/Socks5Forwarder.cs",
    "chars": 25724,
    "preview": "using Shadowsocks.Enums;\nusing Shadowsocks.Model;\nusing Shadowsocks.Proxy;\nusing Shadowsocks.Util.NetUtils;\nusing System"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/SpeedTest.cs",
    "chars": 3169,
    "preview": "using System;\nusing Shadowsocks.Model.Transfer;\n#if DEBUG\nusing System.Collections.Generic;\n#endif\n\nnamespace Shadowsock"
  },
  {
    "path": "shadowsocks-csharp/Controller/Service/UpdateSubscribeManager.cs",
    "chars": 1843,
    "preview": "using Shadowsocks.Controller.HttpRequest;\nusing Shadowsocks.Model;\nusing System.Collections.Generic;\nusing System.Linq;\n"
  },
  {
    "path": "shadowsocks-csharp/Controller/SystemProxy.cs",
    "chars": 1703,
    "preview": "using Shadowsocks.Controller.Service;\nusing Shadowsocks.Enums;\nusing Shadowsocks.Model;\nusing System;\nusing WindowsProxy"
  },
  {
    "path": "shadowsocks-csharp/Data/abp.js",
    "chars": 19640,
    "preview": "var direct = \"__DIRECT__\";\nif (direct == \"__DIR\" + \"ECT__\") direct = \"DIRECT;\";\n\nvar wall_proxy = function(){ return \"__"
  },
  {
    "path": "shadowsocks-csharp/Data/chn_ip.txt",
    "chars": 123354,
    "preview": "1.0.1.0/24\n1.0.2.0/23\n1.0.8.0/21\n1.0.32.0/19\n1.1.0.0/24\n1.1.2.0/23\n1.1.4.0/22\n1.1.8.0/21\n1.1.16.0/20\n1.1.32.0/19\n1.2.0.0"
  },
  {
    "path": "shadowsocks-csharp/Data/proxy.pac.txt",
    "chars": 170862,
    "preview": "var direct = \"__DIRECT__\";\nif (direct == \"__DIR\" + \"ECT__\") direct = \"DIRECT;\";\n\nvar wall_proxy = function(){ return \"__"
  },
  {
    "path": "shadowsocks-csharp/Data/user-rule.txt",
    "chars": 98,
    "preview": "! Put user rules line by line in this file.\r\n! See https://adblockplus.org/en/filter-cheatsheet\r\n"
  },
  {
    "path": "shadowsocks-csharp/Encryption/CircularBuffer/ByteCircularBuffer.cs",
    "chars": 22879,
    "preview": "#region Original License\n\n//New BSD License(BSD)\n//\n//Copyright(c) 2014-2015 Cyotek Ltd\n//Copyright(c) 2012, Alex Reguei"
  },
  {
    "path": "shadowsocks-csharp/Encryption/CryptoUtils.cs",
    "chars": 1321,
    "preview": "using CryptoBase.Abstractions.Digests;\nusing CryptoBase.Digests;\nusing CryptoBase.SymmetricCryptos.BlockCryptos.AES;\nusi"
  },
  {
    "path": "shadowsocks-csharp/Encryption/EncryptorBase.cs",
    "chars": 1121,
    "preview": "namespace Shadowsocks.Encryption\r\n{\r\n    public abstract class EncryptorBase : IEncryptor\r\n    {\r\n        public const i"
  },
  {
    "path": "shadowsocks-csharp/Encryption/EncryptorFactory.cs",
    "chars": 2988,
    "preview": "using Shadowsocks.Encryption.Stream;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System"
  },
  {
    "path": "shadowsocks-csharp/Encryption/EncryptorInfo.cs",
    "chars": 499,
    "preview": "namespace Shadowsocks.Encryption\n{\n    public class EncryptorInfo\n    {\n        public int KeySize;\n        public int I"
  },
  {
    "path": "shadowsocks-csharp/Encryption/Exception/CryptoException.cs",
    "chars": 393,
    "preview": "namespace Shadowsocks.Encryption.Exception\n{\n    public class CryptoErrorException : System.Exception\n    {\n        publ"
  },
  {
    "path": "shadowsocks-csharp/Encryption/IEncryptor.cs",
    "chars": 425,
    "preview": "using System;\r\n\r\nnamespace Shadowsocks.Encryption\r\n{\r\n    public interface IEncryptor : IDisposable\r\n    {\r\n        void"
  },
  {
    "path": "shadowsocks-csharp/Encryption/OpenSSL.cs",
    "chars": 2672,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Properties;\nusing Shadowsocks.Util;\nusing System;\nusing System.IO;\nusing"
  },
  {
    "path": "shadowsocks-csharp/Encryption/Sodium.cs",
    "chars": 2591,
    "preview": "using Shadowsocks.Controller;\r\nusing Shadowsocks.Properties;\r\nusing Shadowsocks.Util;\r\nusing System;\r\nusing System.IO;\r\n"
  },
  {
    "path": "shadowsocks-csharp/Encryption/Stream/NoneEncryptor.cs",
    "chars": 1615,
    "preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Shadowsocks.Encryption.Stream\n{\n    public sealed class NoneE"
  },
  {
    "path": "shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs",
    "chars": 5416,
    "preview": "using Shadowsocks.Crypto;\nusing Shadowsocks.Encryption.CircularBuffer;\nusing Shadowsocks.Proxy;\nusing Shadowsocks.Util;\n"
  },
  {
    "path": "shadowsocks-csharp/Encryption/Stream/StreamOpenSSLEncryptor.cs",
    "chars": 6366,
    "preview": "using Shadowsocks.Encryption.Exception;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\n\nnames"
  },
  {
    "path": "shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs",
    "chars": 4450,
    "preview": "using Shadowsocks.Encryption.Exception;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Shadowsocks.Encryptio"
  },
  {
    "path": "shadowsocks-csharp/Enums/BalanceType.cs",
    "chars": 213,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum BalanceType\n    {\n        OneByOne,\n        Random,\n        FastDownloadSp"
  },
  {
    "path": "shadowsocks-csharp/Enums/DnsType.cs",
    "chars": 104,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum DnsType\n    {\n        Default,\n        DnsOverTls\n    }\n}\n"
  },
  {
    "path": "shadowsocks-csharp/Enums/HttpRequestProxyType.cs",
    "chars": 148,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum HttpRequestProxyType\n    {\n        Auto,\n        Direct,\n        Proxy,\n  "
  },
  {
    "path": "shadowsocks-csharp/Enums/LogLevel.cs",
    "chars": 146,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum LogLevel\n    {\n        Debug = 0,\n        Info,\n        Warn,\n        Erro"
  },
  {
    "path": "shadowsocks-csharp/Enums/PacType.cs",
    "chars": 101,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum PacType\n    {\n        GfwList,\n        Online,\n    }\n}\n"
  },
  {
    "path": "shadowsocks-csharp/Enums/PortMapType.cs",
    "chars": 131,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum PortMapType\n    {\n        Forward = 0,\n        ForceProxy,\n        RulePro"
  },
  {
    "path": "shadowsocks-csharp/Enums/ProxyMode.cs",
    "chars": 132,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum ProxyMode\n    {\n        NoModify,\n        Direct,\n        Pac,\n        Glo"
  },
  {
    "path": "shadowsocks-csharp/Enums/ProxyRuleMode.cs",
    "chars": 195,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum ProxyRuleMode\n    {\n        Disable = 0,\n        BypassLan,\n        Bypass"
  },
  {
    "path": "shadowsocks-csharp/Enums/ProxyType.cs",
    "chars": 122,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum ProxyType\n    {\n        Socks5,\n        Http,\n        TcpPortTunnel\n    }\n"
  },
  {
    "path": "shadowsocks-csharp/Enums/ServerTreeViewType.cs",
    "chars": 125,
    "preview": "namespace Shadowsocks.Enums\n{\n    public enum ServerTreeViewType\n    {\n        Subtag,\n        Group,\n        Server\n   "
  },
  {
    "path": "shadowsocks-csharp/I18N/App.en-US.xaml",
    "chars": 6821,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http:"
  },
  {
    "path": "shadowsocks-csharp/I18N/App.zh-CN.xaml",
    "chars": 5823,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http:"
  },
  {
    "path": "shadowsocks-csharp/I18N/App.zh-TW.xaml",
    "chars": 5908,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http:"
  },
  {
    "path": "shadowsocks-csharp/I18N/ConfigWindow.en-US.xaml",
    "chars": 2048,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/ConfigWindow.zh-CN.xaml",
    "chars": 1875,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/ConfigWindow.zh-TW.xaml",
    "chars": 1874,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/DnsSettingWindow.en-US.xaml",
    "chars": 1425,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/DnsSettingWindow.zh-CN.xaml",
    "chars": 1355,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/DnsSettingWindow.zh-TW.xaml",
    "chars": 1358,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/LogWindow.en-US.xaml",
    "chars": 820,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/LogWindow.zh-CN.xaml",
    "chars": 806,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/LogWindow.zh-TW.xaml",
    "chars": 810,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/PortSettingsWindow.en-US.xaml",
    "chars": 1259,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/PortSettingsWindow.zh-CN.xaml",
    "chars": 1171,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/PortSettingsWindow.zh-TW.xaml",
    "chars": 1175,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/ServerLogWindow.en-US.xaml",
    "chars": 2455,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/ServerLogWindow.zh-CN.xaml",
    "chars": 2271,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/ServerLogWindow.zh-TW.xaml",
    "chars": 2271,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/SettingsWindow.en-US.xaml",
    "chars": 2354,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/SettingsWindow.zh-CN.xaml",
    "chars": 2122,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/SettingsWindow.zh-TW.xaml",
    "chars": 2131,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/SubscribeWindow.en-US.xaml",
    "chars": 1499,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/SubscribeWindow.zh-CN.xaml",
    "chars": 1266,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/I18N/SubscribeWindow.zh-TW.xaml",
    "chars": 1266,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "shadowsocks-csharp/Model/Configuration.cs",
    "chars": 20385,
    "preview": "using Shadowsocks.Enums;\r\nusing Shadowsocks.ViewModel;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.L"
  },
  {
    "path": "shadowsocks-csharp/Model/ConfigurationException.cs",
    "chars": 533,
    "preview": "using System;\n\nnamespace Shadowsocks.Model\n{\n    [Serializable]\n    internal class ConfigurationException : Exception\n  "
  },
  {
    "path": "shadowsocks-csharp/Model/Connections.cs",
    "chars": 1545,
    "preview": "using Shadowsocks.Proxy;\nusing System.Collections.Generic;\n\nnamespace Shadowsocks.Model\n{\n    public class Connections\n "
  },
  {
    "path": "shadowsocks-csharp/Model/DnsBuffer.cs",
    "chars": 818,
    "preview": "using System;\nusing System.Net;\n\nnamespace Shadowsocks.Model\n{\n    public class DnsBuffer\n    {\n        public IPAddress"
  },
  {
    "path": "shadowsocks-csharp/Model/DnsClient.cs",
    "chars": 9443,
    "preview": "using ARSoft.Tools.Net;\nusing ARSoft.Tools.Net.Dns;\nusing Shadowsocks.Enums;\nusing Shadowsocks.ViewModel;\nusing System;\n"
  },
  {
    "path": "shadowsocks-csharp/Model/ErrorLog.cs",
    "chars": 250,
    "preview": "using System;\n\nnamespace Shadowsocks.Model\n{\n    public class ErrorLog\n    {\n        public int errno;\n        public Da"
  },
  {
    "path": "shadowsocks-csharp/Model/Global.cs",
    "chars": 3120,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Controller.HttpRequest;\nusing Shadowsocks.Controller.Service;\nusing Shad"
  },
  {
    "path": "shadowsocks-csharp/Model/HostNode.cs",
    "chars": 559,
    "preview": "using System.Collections.Generic;\n\nnamespace Shadowsocks.Model\n{\n    internal class HostNode\n    {\n        public readon"
  },
  {
    "path": "shadowsocks-csharp/Model/IPRangeSet.cs",
    "chars": 2448,
    "preview": "using RouteMatcher.Abstractions;\nusing RouteMatcher.IPMatchers;\nusing Shadowsocks.Enums;\nusing Shadowsocks.Properties;\nu"
  },
  {
    "path": "shadowsocks-csharp/Model/IPSegment.cs",
    "chars": 5783,
    "preview": "using System;\nusing System.Collections;\nusing System.Net;\n\nnamespace Shadowsocks.Model\n{\n    public class IPAddressCmp :"
  },
  {
    "path": "shadowsocks-csharp/Model/LRUCache.cs",
    "chars": 4078,
    "preview": "using Shadowsocks.Controller;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Shadowsocks.Model\n{\n    public "
  },
  {
    "path": "shadowsocks-csharp/Model/MinSearchTree.cs",
    "chars": 8538,
    "preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Shadowsocks.Model\n{\n    public struct MinSearchTreeNode\n    {"
  },
  {
    "path": "shadowsocks-csharp/Model/PortMapConfig.cs",
    "chars": 1236,
    "preview": "using Shadowsocks.Enums;\nusing Shadowsocks.ViewModel;\nusing System;\n\nnamespace Shadowsocks.Model\n{\n    [Serializable]\n  "
  },
  {
    "path": "shadowsocks-csharp/Model/PortMapConfigCache.cs",
    "chars": 262,
    "preview": "using Shadowsocks.Enums;\n\nnamespace Shadowsocks.Model\n{\n    public class PortMapConfigCache\n    {\n        public PortMap"
  },
  {
    "path": "shadowsocks-csharp/Model/Rule.cs",
    "chars": 134,
    "preview": "namespace Shadowsocks.Model\n{\n    public enum Rule : byte\n    {\n        Unknown,\n        Block,\n        Direct,\n        "
  },
  {
    "path": "shadowsocks-csharp/Model/Server.cs",
    "chars": 17374,
    "preview": "using Shadowsocks.Model.Transfer;\r\nusing Shadowsocks.Util;\r\nusing Shadowsocks.ViewModel;\r\nusing System;\r\nusing System.Co"
  },
  {
    "path": "shadowsocks-csharp/Model/ServerSelectStrategy.cs",
    "chars": 16578,
    "preview": "using Shadowsocks.Enums;\nusing Shadowsocks.Model.Transfer;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Sh"
  },
  {
    "path": "shadowsocks-csharp/Model/ServerSubscribe.cs",
    "chars": 2547,
    "preview": "using Shadowsocks.Controller.HttpRequest;\nusing Shadowsocks.Encryption;\nusing Shadowsocks.Enums;\nusing Shadowsocks.ViewM"
  },
  {
    "path": "shadowsocks-csharp/Model/ServerTreeViewModel.cs",
    "chars": 4255,
    "preview": "using Shadowsocks.Enums;\nusing Shadowsocks.Util;\nusing Shadowsocks.ViewModel;\nusing System;\nusing System.Collections.Gen"
  },
  {
    "path": "shadowsocks-csharp/Model/Transfer/ServerSpeedLog.cs",
    "chars": 20432,
    "preview": "using Shadowsocks.Util;\nusing Shadowsocks.ViewModel;\nusing System;\nusing System.Collections.Concurrent;\nusing System.Col"
  },
  {
    "path": "shadowsocks-csharp/Model/Transfer/ServerTrans.cs",
    "chars": 220,
    "preview": "using System;\n\nnamespace Shadowsocks.Model.Transfer\n{\n    [Serializable]\n    public class ServerTrans\n    {\n        publ"
  },
  {
    "path": "shadowsocks-csharp/Model/Transfer/ServerTransferTotal.cs",
    "chars": 4251,
    "preview": "using Shadowsocks.Util;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System"
  },
  {
    "path": "shadowsocks-csharp/Model/Transfer/TransLog.cs",
    "chars": 428,
    "preview": "using System;\n\nnamespace Shadowsocks.Model.Transfer\n{\n    public class TransLog\n    {\n        public int size;\n        p"
  },
  {
    "path": "shadowsocks-csharp/Model/UriVisitTime.cs",
    "chars": 507,
    "preview": "using System;\n\nnamespace Shadowsocks.Model\n{\n    public class UriVisitTime : IComparable\n    {\n        public DateTime v"
  },
  {
    "path": "shadowsocks-csharp/Model/WindowStatus.cs",
    "chars": 1073,
    "preview": "using Shadowsocks.Util;\nusing System.Windows;\n\nnamespace Shadowsocks.Model\n{\n    public class WindowStatus\n    {\n       "
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthAES128SHA1.cs",
    "chars": 23376,
    "preview": "using CryptoBase.Abstractions;\nusing CryptoBase.Abstractions.Digests;\nusing CryptoBase.Digests;\nusing CryptoBase.Macs.Hm"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthAkarin.cs",
    "chars": 22378,
    "preview": "using CryptoBase.Abstractions;\nusing CryptoBase.Digests;\nusing CryptoBase.Macs.Hmac;\nusing Shadowsocks.Controller;\nusing"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthAkarin_spec_a.cs",
    "chars": 5435,
    "preview": "using System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    class AuthAkarin_spec_a : AuthAkarin\n    {\n        p"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthChain_a.cs",
    "chars": 20114,
    "preview": "using CryptoBase.Abstractions;\nusing CryptoBase.Digests;\nusing CryptoBase.Macs.Hmac;\nusing Shadowsocks.Controller;\nusing"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthChain_b.cs",
    "chars": 3546,
    "preview": "using System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    class AuthChain_b : AuthChain_a\n    {\n        public"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthChain_c.cs",
    "chars": 2398,
    "preview": "using System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    class AuthChain_c : AuthChain_b\n    {\n        public"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthChain_d.cs",
    "chars": 2329,
    "preview": "using System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    class AuthChain_d : AuthChain_c\n    {\n        public"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthChain_e.cs",
    "chars": 1057,
    "preview": "using System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    class AuthChain_e : AuthChain_d\n    {\n        public"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthChain_f.cs",
    "chars": 2655,
    "preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    class AuthChain_f : AuthChain_e\n    {\n"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthData.cs",
    "chars": 148,
    "preview": "namespace Shadowsocks.Obfs\n{\n    public class AuthData : VerifyData\n    {\n        public byte[] clientID;\n        public"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthSHA1.cs",
    "chars": 7073,
    "preview": "using CryptoBase.Digests;\nusing CryptoBase.Macs.Hmac;\nusing System;\nusing System.Collections.Generic;\nusing System.Secur"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthSHA1V2.cs",
    "chars": 8614,
    "preview": "using CryptoBase.Digests;\nusing CryptoBase.Macs.Hmac;\nusing System;\nusing System.Collections.Generic;\nusing System.Secur"
  },
  {
    "path": "shadowsocks-csharp/Obfs/AuthSHA1V4.cs",
    "chars": 9530,
    "preview": "using CryptoBase.Digests;\nusing CryptoBase.Macs.Hmac;\nusing System;\nusing System.Collections.Generic;\nusing System.Secur"
  },
  {
    "path": "shadowsocks-csharp/Obfs/HttpSimpleObfs.cs",
    "chars": 10217,
    "preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    class HttpSimpleObfs : ObfsBase\n    {\n"
  },
  {
    "path": "shadowsocks-csharp/Obfs/IObfs.cs",
    "chars": 927,
    "preview": "using System;\n\nnamespace Shadowsocks.Obfs\n{\n    public interface IObfs : IDisposable\n    {\n        string Name();\n      "
  },
  {
    "path": "shadowsocks-csharp/Obfs/ObfsBase.cs",
    "chars": 3430,
    "preview": "\nusing System;\nusing System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    public abstract class ObfsBase : IObf"
  },
  {
    "path": "shadowsocks-csharp/Obfs/ObfsException.cs",
    "chars": 193,
    "preview": "using System;\n\nnamespace Shadowsocks.Obfs\n{\n    public class ObfsException : Exception\n    {\n        public ObfsExceptio"
  },
  {
    "path": "shadowsocks-csharp/Obfs/ObfsFactory.cs",
    "chars": 3370,
    "preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    public static class ObfsFactory\n    {\n"
  },
  {
    "path": "shadowsocks-csharp/Obfs/Plain.cs",
    "chars": 1051,
    "preview": "using System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    public class Plain : ObfsBase\n    {\n        public P"
  },
  {
    "path": "shadowsocks-csharp/Obfs/ProtocolException.cs",
    "chars": 185,
    "preview": "using System;\n\nnamespace Shadowsocks.Obfs\n{\n    public class ProtocolException : Exception\n    {\n        public Protocol"
  },
  {
    "path": "shadowsocks-csharp/Obfs/ServerInfo.cs",
    "chars": 1029,
    "preview": "namespace Shadowsocks.Obfs\n{\n    public class ServerInfo\n    {\n        public string host;\n        public int port;\n    "
  },
  {
    "path": "shadowsocks-csharp/Obfs/TlsAuthData.cs",
    "chars": 193,
    "preview": "using System.Collections.Generic;\n\nnamespace Shadowsocks.Obfs\n{\n    public class TlsAuthData\n    {\n        public byte[]"
  },
  {
    "path": "shadowsocks-csharp/Obfs/TlsTicketAuthObfs.cs",
    "chars": 16728,
    "preview": "using CryptoBase.Digests;\nusing CryptoBase.Macs.Hmac;\nusing System;\nusing System.Collections.Generic;\nusing System.Secur"
  },
  {
    "path": "shadowsocks-csharp/Obfs/VerifyData.cs",
    "chars": 71,
    "preview": "namespace Shadowsocks.Obfs\n{\n    public class VerifyData\n    {\n    }\n}\n"
  },
  {
    "path": "shadowsocks-csharp/Obfs/VerifyDeflateObfs.cs",
    "chars": 4563,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Util;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Shadows"
  },
  {
    "path": "shadowsocks-csharp/Obfs/VerifySimpleBase.cs",
    "chars": 2588,
    "preview": "using System;\n\nnamespace Shadowsocks.Obfs\n{\n    public abstract class VerifySimpleBase : ObfsBase\n    {\n        public V"
  },
  {
    "path": "shadowsocks-csharp/Obfs/xorshift128plus.cs",
    "chars": 1246,
    "preview": "using System;\n\nnamespace Shadowsocks.Obfs\n{\n    class xorshift128plus\n    {\n        protected ulong v0, v1;\n        prot"
  },
  {
    "path": "shadowsocks-csharp/Program.cs",
    "chars": 7132,
    "preview": "using CryptoBase;\r\nusing Microsoft.Win32;\r\nusing Shadowsocks.Controller;\r\nusing Shadowsocks.Enums;\r\nusing Shadowsocks.Mo"
  },
  {
    "path": "shadowsocks-csharp/Properties/AssemblyInfo.cs",
    "chars": 567,
    "preview": "using System.Reflection;\r\n\r\n[assembly: AssemblyTitle(Shadowsocks.Controller.HttpRequest.UpdateChecker.Name)]\r\n[assembly:"
  },
  {
    "path": "shadowsocks-csharp/Properties/Resources.Designer.cs",
    "chars": 7268,
    "preview": "//------------------------------------------------------------------------------\r\n// <auto-generated>\r\n//     此代码由工具生成。"
  },
  {
    "path": "shadowsocks-csharp/Properties/Resources.resx",
    "chars": 7603,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<root>\r\n  <!-- \r\n    Microsoft ResX Schema \r\n    \r\n    Version 2.0\r\n    \r\n    T"
  },
  {
    "path": "shadowsocks-csharp/Proxy/CallbackState.cs",
    "chars": 193,
    "preview": "namespace Shadowsocks.Proxy\n{\n    public class CallbackState\n    {\n        public byte[] buffer;\n        public int size"
  },
  {
    "path": "shadowsocks-csharp/Proxy/CallbackStatus.cs",
    "chars": 759,
    "preview": "namespace Shadowsocks.Proxy\n{\n    class CallbackStatus\n    {\n        protected int status;\n\n        public CallbackStatu"
  },
  {
    "path": "shadowsocks-csharp/Proxy/Handler.cs",
    "chars": 61504,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Controller.Service;\nusing Shadowsocks.Enums;\nusing Shadowsocks.Model;\nus"
  },
  {
    "path": "shadowsocks-csharp/Proxy/HandlerConfig.cs",
    "chars": 1770,
    "preview": "using Shadowsocks.Enums;\nusing System;\n\nnamespace Shadowsocks.Proxy\n{\n    class HandlerConfig : ICloneable\n    {\n       "
  },
  {
    "path": "shadowsocks-csharp/Proxy/HttpParser.cs",
    "chars": 12783,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Net;\nusing System.Net.Sockets;\nusing Sys"
  },
  {
    "path": "shadowsocks-csharp/Proxy/IHandler.cs",
    "chars": 120,
    "preview": "namespace Shadowsocks.Proxy\n{\n    public abstract class IHandler\n    {\n        public abstract void Shutdown();\n    }\n}\n"
  },
  {
    "path": "shadowsocks-csharp/Proxy/ProxyAuthHandler.cs",
    "chars": 23175,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Controller.Service;\nusing Shadowsocks.Enums;\nusing Shadowsocks.Model;\nus"
  },
  {
    "path": "shadowsocks-csharp/Proxy/ProxyEncryptSocket.cs",
    "chars": 26725,
    "preview": "using Shadowsocks.Encryption;\nusing Shadowsocks.Model;\nusing Shadowsocks.Obfs;\nusing System;\nusing System.Collections.Ge"
  },
  {
    "path": "shadowsocks-csharp/Proxy/ProxySocketTun.cs",
    "chars": 12957,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Net;\nusing System.Net.Sockets;\nusing Sys"
  },
  {
    "path": "shadowsocks-csharp/Proxy/ProxySocketTunLocal.cs",
    "chars": 1654,
    "preview": "using System.Net.Sockets;\n\nnamespace Shadowsocks.Proxy\n{\n    public class ProxySocketTunLocal : ProxySocketTun\n    {\n   "
  },
  {
    "path": "shadowsocks-csharp/SyncfusionLicenseRegister.bat",
    "chars": 618,
    "preview": "@echo on&setlocal\n    setlocal enableextensions disabledelayedexpansion\n\n\t::Arguments of either PreBuild or PostBuild\n\ts"
  },
  {
    "path": "shadowsocks-csharp/Util/Base64.cs",
    "chars": 1323,
    "preview": "using System;\nusing System.Text;\n\nnamespace Shadowsocks.Util\n{\n    public static class Base64\n    {\n        public stati"
  },
  {
    "path": "shadowsocks-csharp/Util/CRC.cs",
    "chars": 1515,
    "preview": "using CryptoBase.Digests;\nusing System;\nusing System.Buffers.Binary;\n\nnamespace Shadowsocks.Util\n{\n    public static cla"
  },
  {
    "path": "shadowsocks-csharp/Util/ColorConvert.cs",
    "chars": 4941,
    "preview": "using System;\nusing System.Linq;\nusing System.Windows.Media;\nusing Color = System.Windows.Media.Color;\n\nnamespace Shadow"
  },
  {
    "path": "shadowsocks-csharp/Util/Constants.cs",
    "chars": 145,
    "preview": "namespace Shadowsocks.Util\n{\n    internal static class Constants\n    {\n        public const string ParameterMultiplyInst"
  },
  {
    "path": "shadowsocks-csharp/Util/I18NUtil.cs",
    "chars": 3153,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Windows;\nusing System.Windows.Controls;\n\nnamespace Shadowso"
  },
  {
    "path": "shadowsocks-csharp/Util/JsonUtils.cs",
    "chars": 675,
    "preview": "using System.Text.Encodings.Web;\nusing System.Text.Json;\n\nnamespace Shadowsocks.Util\n{\n    public static class JsonUtils"
  },
  {
    "path": "shadowsocks-csharp/Util/NetUtils/DnsUtil.cs",
    "chars": 1524,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Model;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System"
  },
  {
    "path": "shadowsocks-csharp/Util/NetUtils/IPSubnet.cs",
    "chars": 4540,
    "preview": "using System;\nusing System.Collections;\nusing System.Linq;\nusing System.Net;\nusing System.Net.Sockets;\n\nnamespace Shadow"
  },
  {
    "path": "shadowsocks-csharp/Util/NetUtils/SocketUtil.cs",
    "chars": 702,
    "preview": "using System;\nusing System.Net.Sockets;\n\nnamespace Shadowsocks.Util.NetUtils\n{\n    public static class SocketUtil\n    {\n"
  },
  {
    "path": "shadowsocks-csharp/Util/NetUtils/WrappedSocket.cs",
    "chars": 8306,
    "preview": "using System;\nusing System.Net;\nusing System.Net.Sockets;\nusing System.Threading;\n\nnamespace Shadowsocks.Util.NetUtils\n{"
  },
  {
    "path": "shadowsocks-csharp/Util/QrCodeUtils.cs",
    "chars": 2617,
    "preview": "using System;\nusing System.Drawing;\nusing System.IO;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\nusi"
  },
  {
    "path": "shadowsocks-csharp/Util/RNG.cs",
    "chars": 260,
    "preview": "using System;\nusing System.Security.Cryptography;\n\nnamespace Shadowsocks.Util;\n\npublic static class Rng\n{\n    public sta"
  },
  {
    "path": "shadowsocks-csharp/Util/Reg.cs",
    "chars": 831,
    "preview": "using System.Diagnostics;\nusing URIScheme;\n\nnamespace Shadowsocks.Util\n{\n    public static class Reg\n    {\n        [Cond"
  },
  {
    "path": "shadowsocks-csharp/Util/Utils.cs",
    "chars": 6685,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Encryption;\nusing Shadowsocks.Model;\nusing System;\nusing System.Collecti"
  },
  {
    "path": "shadowsocks-csharp/Util/ViewUtils.cs",
    "chars": 6084,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Drawing.Drawing2D;\nusing System.Linq;"
  },
  {
    "path": "shadowsocks-csharp/View/Controls/BindablePasswordBox.cs",
    "chars": 2931,
    "preview": "using System.Windows;\nusing System.Windows.Controls;\n\nnamespace Shadowsocks.View.Controls\n{\n    public sealed class Bind"
  },
  {
    "path": "shadowsocks-csharp/View/Controls/GridColumnSizerExt.cs",
    "chars": 933,
    "preview": "using Syncfusion.UI.Xaml.Grid;\nusing System.Linq;\nusing System.Windows;\n\nnamespace Shadowsocks.View.Controls\n{\n    publi"
  },
  {
    "path": "shadowsocks-csharp/View/Controls/MaskedTextBox.xaml",
    "chars": 663,
    "preview": "<UserControl x:Class=\"Shadowsocks.View.Controls.MaskedTextBox\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2"
  },
  {
    "path": "shadowsocks-csharp/View/Controls/MaskedTextBox.xaml.cs",
    "chars": 1853,
    "preview": "using System;\nusing System.Windows;\n\nnamespace Shadowsocks.View.Controls\n{\n    public partial class MaskedTextBox\n    {\n"
  },
  {
    "path": "shadowsocks-csharp/View/Controls/NumberUpDown.xaml",
    "chars": 1295,
    "preview": "<UserControl x:Class=\"Shadowsocks.View.Controls.NumberUpDown\"\n             xmlns=\"http://schemas.microsoft.com/winfx/20"
  },
  {
    "path": "shadowsocks-csharp/View/Controls/NumberUpDown.xaml.cs",
    "chars": 2696,
    "preview": "using System;\nusing System.Windows;\nusing System.Windows.Controls;\n\nnamespace Shadowsocks.View.Controls\n{\n    public par"
  },
  {
    "path": "shadowsocks-csharp/View/DnsSettingWindow.xaml",
    "chars": 10030,
    "preview": "<Window x:Class=\"Shadowsocks.View.DnsSettingWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/present"
  },
  {
    "path": "shadowsocks-csharp/View/DnsSettingWindow.xaml.cs",
    "chars": 2686,
    "preview": "using Shadowsocks.Util;\nusing Shadowsocks.ViewModel;\nusing System.Threading.Tasks;\nusing System.Windows;\nusing System.Wi"
  },
  {
    "path": "shadowsocks-csharp/View/LogWindow.xaml",
    "chars": 2304,
    "preview": "<Window x:Class=\"Shadowsocks.View.LogWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n"
  },
  {
    "path": "shadowsocks-csharp/View/LogWindow.xaml.cs",
    "chars": 5298,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Util;\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing Sys"
  },
  {
    "path": "shadowsocks-csharp/View/NotifyIconResources.xaml",
    "chars": 3226,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http:"
  },
  {
    "path": "shadowsocks-csharp/View/PortSettingsWindow.xaml",
    "chars": 5669,
    "preview": "<Window\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n        xmlns:x=\"http://schemas.micro"
  },
  {
    "path": "shadowsocks-csharp/View/PortSettingsWindow.xaml.cs",
    "chars": 12466,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Enums;\nusing Shadowsocks.Model;\nusing Shadowsocks.Util;\nusing Shadowsock"
  },
  {
    "path": "shadowsocks-csharp/View/QRCodeSplashWindow.xaml",
    "chars": 702,
    "preview": "<Window x:Class=\"Shadowsocks.View.QRCodeSplashWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/prese"
  },
  {
    "path": "shadowsocks-csharp/View/QRCodeSplashWindow.xaml.cs",
    "chars": 3005,
    "preview": "using System;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.Threading.Tasks;\nusing System.Windows;\n\nnames"
  },
  {
    "path": "shadowsocks-csharp/View/ServerConfigWindow.xaml",
    "chars": 16765,
    "preview": "<Window x:Class=\"Shadowsocks.View.ServerConfigWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/prese"
  },
  {
    "path": "shadowsocks-csharp/View/ServerConfigWindow.xaml.cs",
    "chars": 18802,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Encryption;\nusing Shadowsocks.Enums;\nusing Shadowsocks.Model;\nusing Shad"
  },
  {
    "path": "shadowsocks-csharp/View/ServerLogWindow.xaml",
    "chars": 20940,
    "preview": "<Window x:Class=\"Shadowsocks.View.ServerLogWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentat"
  },
  {
    "path": "shadowsocks-csharp/View/ServerLogWindow.xaml.cs",
    "chars": 15603,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Controller.HttpRequest;\nusing Shadowsocks.Model;\nusing Shadowsocks.Util;"
  },
  {
    "path": "shadowsocks-csharp/View/SettingsWindow.xaml",
    "chars": 13549,
    "preview": "<Window x:Class=\"Shadowsocks.View.SettingsWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentat"
  },
  {
    "path": "shadowsocks-csharp/View/SettingsWindow.xaml.cs",
    "chars": 3336,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Controller.HttpRequest;\nusing Shadowsocks.Model;\nusing Shadowsocks.Util;"
  },
  {
    "path": "shadowsocks-csharp/View/ShowTextWindow.xaml",
    "chars": 1031,
    "preview": "<Window x:Class=\"Shadowsocks.View.ShowTextWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentat"
  },
  {
    "path": "shadowsocks-csharp/View/ShowTextWindow.xaml.cs",
    "chars": 1432,
    "preview": "using Shadowsocks.Util;\nusing System;\nusing System.Windows;\n\nnamespace Shadowsocks.View\n{\n    public partial class ShowT"
  },
  {
    "path": "shadowsocks-csharp/View/SubscribeWindow.xaml",
    "chars": 7684,
    "preview": "<Window x:Class=\"Shadowsocks.View.SubscribeWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentat"
  },
  {
    "path": "shadowsocks-csharp/View/SubscribeWindow.xaml.cs",
    "chars": 6938,
    "preview": "using Shadowsocks.Controller;\nusing Shadowsocks.Model;\nusing Shadowsocks.Util;\nusing Shadowsocks.ViewModel;\nusing System"
  }
]

// ... and 23 more files (download for full content)

About this extraction

This page contains the full source code of the HMBSbige/ShadowsocksR-Windows GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 223 files (1.3 MB), approximately 373.2k tokens, and a symbol index with 1322 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!