├── .gitignore ├── MaterialSkin ├── Animations │ ├── AnimationDirection.cs │ ├── AnimationManager.cs │ └── Animations.cs ├── ColorScheme.cs ├── Controls │ ├── MaterialCheckbox.cs │ ├── MaterialContextMenuStrip.cs │ ├── MaterialDivider.cs │ ├── MaterialFlatButton.cs │ ├── MaterialForm.cs │ ├── MaterialLabel.cs │ ├── MaterialListView.cs │ ├── MaterialMenuStrip.cs │ ├── MaterialProgressBar.cs │ ├── MaterialRadioButton.cs │ ├── MaterialRaisedButton.cs │ ├── MaterialSingleLineTextField.cs │ ├── MaterialTabControl.cs │ └── MaterialTabSelector.cs ├── DrawHelper.cs ├── IMaterialControl.cs ├── MaterialSkin.csproj ├── MaterialSkinManager.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx └── Resources │ ├── Roboto-Medium.ttf │ └── Roboto-Regular.ttf ├── README.md ├── shadowsocks-csharp.sln └── shadowsocks-csharp ├── Config └── Constants.cs ├── Controller ├── FileManager.cs ├── I18N.cs ├── Logging.cs ├── Service │ ├── AvailabilityStatistics.cs │ ├── GfwListUpdater.cs │ ├── Listener.cs │ ├── PACServer.cs │ ├── PortForwarder.cs │ ├── PrivoxyRunner.cs │ ├── Sip003Plugin.cs │ ├── TCPRelay.cs │ ├── UDPRelay.cs │ └── UpdateChecker.cs ├── ShadowsocksController.cs ├── Strategy │ ├── BalancingStrategy.cs │ ├── HighAvailabilityStrategy.cs │ ├── IStrategy.cs │ ├── StatisticsStrategy.cs │ └── StrategyManager.cs └── System │ ├── AutoStartup.cs │ ├── Hotkeys │ ├── HotkeyCallbacks.cs │ └── Hotkeys.cs │ └── SystemProxy.cs ├── Data ├── abp.js.gz ├── libsscrypto.dll.gz ├── mgwz.dll.gz ├── privoxy.exe.gz ├── privoxy_conf.txt ├── proxy.pac.txt.gz ├── sysproxy.exe.gz ├── sysproxy64.exe.gz └── user-rule.txt ├── Encryption ├── AEAD │ ├── AEADEncryptor.cs │ ├── AEADMbedTLSEncryptor.cs │ └── AEADSodiumEncryptor.cs ├── CircularBuffer │ └── ByteCircularBuffer.cs ├── DES.cs ├── EncryptorBase.cs ├── EncryptorFactory.cs ├── Exception │ └── CryptoException.cs ├── IEncryptor.cs ├── MbedTLS.cs ├── RNG.cs ├── Sodium.cs └── Stream │ ├── StreamEncryptor.cs │ ├── StreamMbedTLSEncryptor.cs │ └── StreamSodiumEncryptor.cs ├── Exceptions └── AlleyException.cs ├── Extensions ├── JsonExtensions.cs └── StringExtensions.cs ├── FodyWeavers.xml ├── Model ├── Configuration.cs ├── HotKeyConfig.cs ├── LogViewerConfig.cs ├── ProxyConfig.cs ├── Server.cs ├── ServerNode.cs ├── SiteConfig.cs ├── StatisticsRecord.cs ├── StatisticsStrategyConfiguration.cs ├── SysproxyConfig.cs └── User.cs ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── DataSources │ └── Shadowsocks.Model.StatisticsStrategyConfiguration.datasource ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs └── Settings.settings ├── Proxy ├── DirectConnect.cs ├── HttpProxy.cs ├── IProxy.cs └── Socks5Proxy.cs ├── Resources ├── flag │ ├── flag-canada.png │ ├── flag-china.png │ ├── flag-finland.png │ ├── flag-france.png │ ├── flag-germany.png │ ├── flag-hongkong.png │ ├── flag-ireland.png │ ├── flag-italy.png │ ├── flag-japan.png │ ├── flag-korea.png │ ├── flag-norway.png │ ├── flag-russia.png │ ├── flag-spain.png │ ├── flag-taiwan.png │ ├── flag-uk.png │ ├── flag-usa.png │ └── flag_holland.png ├── ico-check.png ├── ico-in24.png ├── ico-out24.png ├── ico-vip.png ├── ico_connecting.gif ├── ico_connection_stop.png ├── ico_loading.gif ├── logo-white.png ├── logo.png ├── logo32.png ├── logo40.png └── logo48.png ├── Settings.cs ├── StringEx.cs ├── Util ├── DateHelper.cs ├── ProcessManagement │ ├── Job.cs │ └── ThreadUtil.cs ├── Request.cs ├── Sockets │ ├── LineReader.cs │ ├── SocketUtil.cs │ └── WrappedSocket.cs ├── SystemProxy │ ├── INTERNET_OPTION.cs │ ├── INTERNET_PER_CONN_OPTION.cs │ ├── INTERNET_PER_CONN_OPTION_LIST.cs │ ├── NativeMethods.cs │ ├── ProxyException.cs │ ├── RAS.cs │ ├── Sysproxy.cs │ └── WinINet.cs ├── Util.cs ├── ValidateHelper.cs └── ViewUtils.cs ├── View ├── Log.Designer.cs ├── Log.cs ├── Log.resx ├── Login.Designer.cs ├── Login.cs ├── Login.resx ├── Main.Designer.cs ├── Main.cs ├── Main.resx ├── MenuViewController.cs ├── Notice.Designer.cs ├── Notice.cs ├── Notice.resx ├── Setting.Designer.cs ├── Setting.cs ├── Setting.resx └── ViewManager.cs ├── app.config ├── app.manifest ├── logo.ico ├── logo.png ├── packages.config ├── shadowsocks-csharp.csproj └── shadowsocks-csharp.csproj.user /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | __tests__ 4 | bin/Debug/ 5 | bin/Release/ 6 | packages 7 | build/ 8 | *.exe 9 | .vs 10 | Debug/ 11 | Release/ -------------------------------------------------------------------------------- /MaterialSkin/Animations/AnimationDirection.cs: -------------------------------------------------------------------------------- 1 | namespace MaterialSkin.Animations 2 | { 3 | enum AnimationDirection 4 | { 5 | In, //In. Stops if finished. 6 | Out, //Out. Stops if finished. 7 | InOutIn, //Same as In, but changes to InOutOut if finished. 8 | InOutOut, //Same as Out. 9 | InOutRepeatingIn, // Same as In, but changes to InOutRepeatingOut if finished. 10 | InOutRepeatingOut // Same as Out, but changes to InOutRepeatingIn if finished. 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MaterialSkin/Animations/Animations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialSkin.Animations 4 | { 5 | enum AnimationType 6 | { 7 | Linear, 8 | EaseInOut, 9 | EaseOut, 10 | CustomQuadratic 11 | } 12 | 13 | static class AnimationLinear 14 | { 15 | public static double CalculateProgress(double progress) 16 | { 17 | return progress; 18 | } 19 | } 20 | 21 | static class AnimationEaseInOut 22 | { 23 | public static double PI = Math.PI; 24 | public static double PI_HALF = Math.PI / 2; 25 | 26 | public static double CalculateProgress(double progress) 27 | { 28 | return EaseInOut(progress); 29 | } 30 | 31 | private static double EaseInOut(double s) 32 | { 33 | return s - Math.Sin(s * 2 * PI) / (2 * PI); 34 | } 35 | } 36 | 37 | public static class AnimationEaseOut 38 | { 39 | public static double CalculateProgress(double progress) 40 | { 41 | return -1 * progress * (progress - 2); 42 | } 43 | } 44 | 45 | public static class AnimationCustomQuadratic 46 | { 47 | public static double CalculateProgress(double progress) 48 | { 49 | var kickoff = 0.6; 50 | return 1 - Math.Cos((Math.Max(progress, kickoff) - kickoff) * Math.PI / (2 - (2 * kickoff))); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MaterialSkin/Controls/MaterialDivider.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows.Forms; 3 | 4 | namespace MaterialSkin.Controls 5 | { 6 | public sealed class MaterialDivider : Control, IMaterialControl 7 | { 8 | [Browsable(false)] 9 | public int Depth { get; set; } 10 | [Browsable(false)] 11 | public MaterialSkinManager SkinManager => MaterialSkinManager.Instance; 12 | [Browsable(false)] 13 | public MouseState MouseState { get; set; } 14 | 15 | public MaterialDivider() 16 | { 17 | SetStyle(ControlStyles.SupportsTransparentBackColor, true); 18 | Height = 1; 19 | BackColor = SkinManager.GetDividersColor(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MaterialSkin/Controls/MaterialLabel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows.Forms; 3 | 4 | namespace MaterialSkin.Controls 5 | { 6 | public class MaterialLabel : Label, IMaterialControl 7 | { 8 | [Browsable(false)] 9 | public int Depth { get; set; } 10 | [Browsable(false)] 11 | public MaterialSkinManager SkinManager => MaterialSkinManager.Instance; 12 | [Browsable(false)] 13 | public MouseState MouseState { get; set; } 14 | protected override void OnCreateControl() 15 | { 16 | base.OnCreateControl(); 17 | 18 | ForeColor = SkinManager.GetPrimaryTextColor(); 19 | Font = SkinManager.ROBOTO_REGULAR_11; 20 | 21 | BackColorChanged += (sender, args) => ForeColor = SkinManager.GetPrimaryTextColor(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MaterialSkin/Controls/MaterialMenuStrip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Drawing.Drawing2D; 5 | using System.Drawing.Text; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace MaterialSkin.Controls 12 | { 13 | public class MaterialMenuStrip : MenuStrip, IMaterialControl 14 | { 15 | public int Depth { get; set; } 16 | public MaterialSkinManager SkinManager { get { return MaterialSkinManager.Instance; } } 17 | public MouseState MouseState { get; set; } 18 | 19 | public MaterialMenuStrip() 20 | { 21 | Renderer = new MaterialMenuStripRender(); 22 | 23 | if (DesignMode) 24 | { 25 | Dock = DockStyle.None; 26 | Anchor |= AnchorStyles.Right; 27 | AutoSize = false; 28 | Location = new Point(0, 28); 29 | } 30 | } 31 | 32 | protected override void OnCreateControl() 33 | { 34 | base.OnCreateControl(); 35 | Font = SkinManager.ROBOTO_MEDIUM_10; 36 | BackColor = SkinManager.PrimaryColor; 37 | } 38 | } 39 | 40 | internal class MaterialMenuStripRender : ToolStripProfessionalRenderer, IMaterialControl 41 | { 42 | //Properties for managing the material design properties 43 | public int Depth { get; set; } 44 | public MaterialSkinManager SkinManager { get { return MaterialSkinManager.Instance; } } 45 | public MouseState MouseState { get; set; } 46 | 47 | protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) 48 | { 49 | var g = e.Graphics; 50 | g.TextRenderingHint = TextRenderingHint.AntiAlias; 51 | 52 | if (e.Item.IsOnDropDown) 53 | { 54 | var itemRect = GetItemRect(e.Item); 55 | var textRect = new Rectangle(24, itemRect.Y, itemRect.Width - (24 + 16), itemRect.Height); 56 | g.DrawString(e.Text, SkinManager.ROBOTO_MEDIUM_10, e.Item.Enabled ? SkinManager.GetMainTextBrush() : SkinManager.GetDisabledOrHintBrush(), textRect, new StringFormat() { LineAlignment = StringAlignment.Center }); 57 | } 58 | else 59 | { 60 | g.DrawString(e.Text, SkinManager.ROBOTO_MEDIUM_10, Brushes.White, e.TextRectangle, new StringFormat() { LineAlignment = StringAlignment.Center }); 61 | } 62 | } 63 | 64 | protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) 65 | { 66 | var g = e.Graphics; 67 | g.Clear(SkinManager.PrimaryColor); 68 | 69 | //Draw background 70 | var itemRect = GetItemRect(e.Item); 71 | if (e.Item.IsOnDropDown) 72 | { 73 | g.FillRectangle(e.Item.Selected && e.Item.Enabled ? SkinManager.GetCmsSelectedItemBrush() : new SolidBrush(SkinManager.GetApplicationBackgroundColor()), itemRect); 74 | } 75 | else 76 | { 77 | g.FillRectangle(e.Item.Selected ? SkinManager.GetFlatButtonPressedBackgroundBrush() : SkinManager.PrimaryColorBrush, itemRect); 78 | } 79 | 80 | //Ripple animation 81 | var toolStrip = e.ToolStrip as MaterialContextMenuStrip; 82 | if (toolStrip != null) 83 | { 84 | var animationManager = toolStrip.animationManager; 85 | var animationSource = toolStrip.animationSource; 86 | if (toolStrip.animationManager.IsAnimating() && e.Item.Bounds.Contains(animationSource)) 87 | { 88 | for (int i = 0; i < animationManager.GetAnimationCount(); i++) 89 | { 90 | var animationValue = animationManager.GetProgress(i); 91 | var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationValue * 50)), Color.Black)); 92 | var rippleSize = (int)(animationValue * itemRect.Width * 2.5); 93 | g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - rippleSize / 2, itemRect.Y - itemRect.Height, rippleSize, itemRect.Height * 3)); 94 | } 95 | } 96 | } 97 | } 98 | 99 | protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) 100 | { 101 | //base.OnRenderImageMargin(e); 102 | } 103 | 104 | protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) 105 | { 106 | var g = e.Graphics; 107 | 108 | g.FillRectangle(new SolidBrush(SkinManager.GetApplicationBackgroundColor()), e.Item.Bounds); 109 | g.DrawLine(new Pen(SkinManager.GetDividersColor()), new Point(e.Item.Bounds.Left, e.Item.Bounds.Height / 2), new Point(e.Item.Bounds.Right, e.Item.Bounds.Height / 2)); 110 | } 111 | 112 | protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) 113 | { 114 | //var g = e.Graphics; 115 | 116 | //g.DrawRectangle(new Pen(SkinManager.GetDividersColor()), new Rectangle(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1)); 117 | } 118 | 119 | protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e) 120 | { 121 | var g = e.Graphics; 122 | const int ARROW_SIZE = 4; 123 | 124 | var arrowMiddle = new Point(e.ArrowRectangle.X + e.ArrowRectangle.Width / 2, e.ArrowRectangle.Y + e.ArrowRectangle.Height / 2); 125 | var arrowBrush = e.Item.Enabled ? SkinManager.GetMainTextBrush() : SkinManager.GetDisabledOrHintBrush(); 126 | using (var arrowPath = new GraphicsPath()) 127 | { 128 | arrowPath.AddLines(new[] { new Point(arrowMiddle.X - ARROW_SIZE, arrowMiddle.Y - ARROW_SIZE), new Point(arrowMiddle.X, arrowMiddle.Y), new Point(arrowMiddle.X - ARROW_SIZE, arrowMiddle.Y + ARROW_SIZE) }); 129 | arrowPath.CloseFigure(); 130 | 131 | g.FillPath(arrowBrush, arrowPath); 132 | } 133 | } 134 | 135 | private Rectangle GetItemRect(ToolStripItem item) 136 | { 137 | return new Rectangle(0, item.ContentRectangle.Y, item.ContentRectangle.Width + 4, item.ContentRectangle.Height); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /MaterialSkin/Controls/MaterialProgressBar.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows.Forms; 3 | 4 | namespace MaterialSkin.Controls 5 | { 6 | /// 7 | /// Material design-like progress bar 8 | /// 9 | public class MaterialProgressBar : ProgressBar, IMaterialControl 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | public MaterialProgressBar() 15 | { 16 | SetStyle(ControlStyles.UserPaint, true); 17 | SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 18 | } 19 | 20 | /// 21 | /// Gets or sets the depth. 22 | /// 23 | /// 24 | /// The depth. 25 | /// 26 | [Browsable(false)] 27 | public int Depth { get; set; } 28 | 29 | /// 30 | /// Gets the skin manager. 31 | /// 32 | /// 33 | /// The skin manager. 34 | /// 35 | [Browsable(false)] 36 | public MaterialSkinManager SkinManager => MaterialSkinManager.Instance; 37 | 38 | /// 39 | /// Gets or sets the state of the mouse. 40 | /// 41 | /// 42 | /// The state of the mouse. 43 | /// 44 | [Browsable(false)] 45 | public MouseState MouseState { get; set; } 46 | 47 | /// 48 | /// Performs the work of setting the specified bounds of this control. 49 | /// 50 | /// The new property value of the control. 51 | /// The new property value of the control. 52 | /// The new property value of the control. 53 | /// The new property value of the control. 54 | /// A bitwise combination of the values. 55 | protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) 56 | { 57 | base.SetBoundsCore(x, y, width, 5, specified); 58 | } 59 | 60 | /// 61 | /// Raises the event. 62 | /// 63 | /// A that contains the event data. 64 | protected override void OnPaint(PaintEventArgs e) 65 | { 66 | var doneProgress = (int)(e.ClipRectangle.Width * ((double)Value / Maximum)); 67 | e.Graphics.FillRectangle(SkinManager.ColorScheme.PrimaryBrush, 0, 0, doneProgress, e.ClipRectangle.Height); 68 | e.Graphics.FillRectangle(SkinManager.GetDisabledOrHintBrush(), doneProgress, 0, e.ClipRectangle.Width, e.ClipRectangle.Height); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /MaterialSkin/Controls/MaterialRaisedButton.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Drawing; 3 | using System.Drawing.Drawing2D; 4 | using System.Drawing.Text; 5 | using System.Windows.Forms; 6 | using MaterialSkin.Animations; 7 | using System; 8 | 9 | namespace MaterialSkin.Controls 10 | { 11 | public class MaterialRaisedButton : Button, IMaterialControl 12 | { 13 | [Browsable(false)] 14 | public int Depth { get; set; } 15 | [Browsable(false)] 16 | public MaterialSkinManager SkinManager => MaterialSkinManager.Instance; 17 | [Browsable(false)] 18 | public MouseState MouseState { get; set; } 19 | public bool Primary { get; set; } 20 | 21 | private readonly AnimationManager _animationManager; 22 | 23 | private SizeF _textSize; 24 | 25 | private Image _icon; 26 | public Image Icon 27 | { 28 | get { return _icon; } 29 | set 30 | { 31 | _icon = value; 32 | if (AutoSize) 33 | Size = GetPreferredSize(); 34 | Invalidate(); 35 | } 36 | } 37 | 38 | public MaterialRaisedButton() 39 | { 40 | Primary = true; 41 | 42 | _animationManager = new AnimationManager(false) 43 | { 44 | Increment = 0.03, 45 | AnimationType = AnimationType.EaseOut 46 | }; 47 | _animationManager.OnAnimationProgress += sender => Invalidate(); 48 | 49 | AutoSizeMode = AutoSizeMode.GrowAndShrink; 50 | AutoSize = true; 51 | } 52 | 53 | public override string Text 54 | { 55 | get { return base.Text; } 56 | set 57 | { 58 | base.Text = value; 59 | _textSize = CreateGraphics().MeasureString(value.ToUpper(), SkinManager.ROBOTO_MEDIUM_10); 60 | if (AutoSize) 61 | Size = GetPreferredSize(); 62 | Invalidate(); 63 | } 64 | } 65 | 66 | protected override void OnMouseUp(MouseEventArgs mevent) 67 | { 68 | base.OnMouseUp(mevent); 69 | 70 | _animationManager.StartNewAnimation(AnimationDirection.In, mevent.Location); 71 | } 72 | 73 | protected override void OnPaint(PaintEventArgs pevent) 74 | { 75 | var g = pevent.Graphics; 76 | g.SmoothingMode = SmoothingMode.AntiAlias; 77 | g.TextRenderingHint = TextRenderingHint.AntiAlias; 78 | 79 | g.Clear(Parent.BackColor); 80 | 81 | using (var backgroundPath = DrawHelper.CreateRoundRect(ClientRectangle.X, 82 | ClientRectangle.Y, 83 | ClientRectangle.Width - 1, 84 | ClientRectangle.Height - 1, 85 | 1f)) 86 | { 87 | g.FillPath(Primary ? SkinManager.ColorScheme.PrimaryBrush : SkinManager.GetRaisedButtonBackgroundBrush(), backgroundPath); 88 | } 89 | 90 | if (_animationManager.IsAnimating()) 91 | { 92 | for (int i = 0; i < _animationManager.GetAnimationCount(); i++) 93 | { 94 | var animationValue = _animationManager.GetProgress(i); 95 | var animationSource = _animationManager.GetSource(i); 96 | var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationValue * 50)), Color.White)); 97 | var rippleSize = (int)(animationValue * Width * 2); 98 | g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize)); 99 | } 100 | } 101 | 102 | //Icon 103 | var iconRect = new Rectangle(8, 6, 24, 24); 104 | 105 | if (string.IsNullOrEmpty(Text)) 106 | // Center Icon 107 | iconRect.X += 2; 108 | 109 | if (Icon != null) 110 | g.DrawImage(Icon, iconRect); 111 | 112 | //Text 113 | var textRect = ClientRectangle; 114 | 115 | if (Icon != null) 116 | { 117 | // 118 | // Resize and move Text container 119 | // 120 | 121 | // First 8: left padding 122 | // 24: icon width 123 | // Second 4: space between Icon and Text 124 | // Third 8: right padding 125 | textRect.Width -= 8 + 24 + 4 + 8; 126 | 127 | // First 8: left padding 128 | // 24: icon width 129 | // Second 4: space between Icon and Text 130 | textRect.X += 8 + 24 + 4; 131 | } 132 | 133 | g.DrawString( 134 | Text.ToUpper(), 135 | SkinManager.ROBOTO_MEDIUM_10, 136 | SkinManager.GetRaisedButtonTextBrush(Primary), 137 | textRect, 138 | new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); 139 | } 140 | 141 | private Size GetPreferredSize() 142 | { 143 | return GetPreferredSize(new Size(0, 0)); 144 | } 145 | 146 | public override Size GetPreferredSize(Size proposedSize) 147 | { 148 | // Provides extra space for proper padding for content 149 | var extra = 16; 150 | 151 | if (Icon != null) 152 | // 24 is for icon size 153 | // 4 is for the space between icon & text 154 | extra += 24 + 4; 155 | 156 | return new Size((int)Math.Ceiling(_textSize.Width) + extra, 36); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /MaterialSkin/Controls/MaterialTabControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Windows.Forms; 4 | 5 | namespace MaterialSkin.Controls 6 | { 7 | public class MaterialTabControl : TabControl, IMaterialControl 8 | { 9 | [Browsable(false)] 10 | public int Depth { get; set; } 11 | [Browsable(false)] 12 | public MaterialSkinManager SkinManager => MaterialSkinManager.Instance; 13 | [Browsable(false)] 14 | public MouseState MouseState { get; set; } 15 | 16 | protected override void WndProc(ref Message m) 17 | { 18 | if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1; 19 | else base.WndProc(ref m); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MaterialSkin/DrawHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Drawing.Drawing2D; 3 | 4 | namespace MaterialSkin 5 | { 6 | static class DrawHelper 7 | { 8 | public static GraphicsPath CreateRoundRect(float x, float y, float width, float height, float radius) 9 | { 10 | var gp = new GraphicsPath(); 11 | gp.AddLine(x + radius, y, x + width - (radius * 2), y); 12 | gp.AddArc(x + width - (radius * 2), y, radius * 2, radius * 2, 270, 90); 13 | gp.AddLine(x + width, y + radius, x + width, y + height - (radius * 2)); 14 | gp.AddArc(x + width - (radius * 2), y + height - (radius * 2), radius * 2, radius * 2, 0, 90); 15 | gp.AddLine(x + width - (radius * 2), y + height, x + radius, y + height); 16 | gp.AddArc(x, y + height - (radius * 2), radius * 2, radius * 2, 90, 90); 17 | gp.AddLine(x, y + height - (radius * 2), x, y + radius); 18 | gp.AddArc(x, y, radius * 2, radius * 2, 180, 90); 19 | gp.CloseFigure(); 20 | return gp; 21 | } 22 | 23 | public static GraphicsPath CreateRoundRect(Rectangle rect, float radius) 24 | { 25 | return CreateRoundRect(rect.X, rect.Y, rect.Width, rect.Height, radius); 26 | } 27 | 28 | public static Color BlendColor(Color backgroundColor, Color frontColor, double blend) 29 | { 30 | var ratio = blend / 255d; 31 | var invRatio = 1d - ratio; 32 | var r = (int)((backgroundColor.R * invRatio) + (frontColor.R * ratio)); 33 | var g = (int)((backgroundColor.G * invRatio) + (frontColor.G * ratio)); 34 | var b = (int)((backgroundColor.B * invRatio) + (frontColor.B * ratio)); 35 | return Color.FromArgb(r, g, b); 36 | } 37 | 38 | public static Color BlendColor(Color backgroundColor, Color frontColor) 39 | { 40 | return BlendColor(backgroundColor, frontColor, frontColor.A); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /MaterialSkin/IMaterialControl.cs: -------------------------------------------------------------------------------- 1 | namespace MaterialSkin 2 | { 3 | public interface IMaterialControl 4 | { 5 | int Depth { get; set; } 6 | MaterialSkinManager SkinManager { get; } 7 | MouseState MouseState { get; set; } 8 | 9 | } 10 | 11 | public enum MouseState 12 | { 13 | HOVER, 14 | DOWN, 15 | OUT 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MaterialSkin/MaterialSkin.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8EB7611B-68CD-4B8B-987A-11717E2B250C} 8 | Library 9 | Properties 10 | MaterialSkin 11 | MaterialSkin 12 | v4.6.1 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | true 35 | bin\x86\Debug\ 36 | DEBUG;TRACE 37 | full 38 | x86 39 | prompt 40 | MinimumRecommendedRules.ruleset 41 | 42 | 43 | bin\x86\Release\ 44 | TRACE 45 | true 46 | pdbonly 47 | x86 48 | prompt 49 | MinimumRecommendedRules.ruleset 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Component 64 | 65 | 66 | Component 67 | 68 | 69 | Component 70 | 71 | 72 | Component 73 | 74 | 75 | Form 76 | 77 | 78 | Component 79 | 80 | 81 | Component 82 | 83 | 84 | Component 85 | 86 | 87 | Component 88 | 89 | 90 | Component 91 | 92 | 93 | Component 94 | 95 | 96 | Component 97 | 98 | 99 | 100 | 101 | Component 102 | 103 | 104 | 105 | 106 | True 107 | True 108 | Resources.resx 109 | 110 | 111 | 112 | 113 | ResXFileCodeGenerator 114 | Resources.Designer.cs 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 131 | -------------------------------------------------------------------------------- /MaterialSkin/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("MaterialSkin")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("MaterialSkin")] 12 | [assembly: AssemblyCopyright("Copyright © 2014")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("52781de3-a323-49ee-9a4f-c67280f8d328")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /MaterialSkin/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace MaterialSkin.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MaterialSkin.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Byte[]. 65 | /// 66 | internal static byte[] Roboto_Medium { 67 | get { 68 | object obj = ResourceManager.GetObject("Roboto_Medium", resourceCulture); 69 | return ((byte[])(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Byte[]. 75 | /// 76 | internal static byte[] Roboto_Regular { 77 | get { 78 | object obj = ResourceManager.GetObject("Roboto_Regular", resourceCulture); 79 | return ((byte[])(obj)); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /MaterialSkin/Resources/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/MaterialSkin/Resources/Roboto-Medium.ttf -------------------------------------------------------------------------------- /MaterialSkin/Resources/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/MaterialSkin/Resources/Roboto-Regular.ttf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 绿点加速器windows客户端 2 | 3 | #### 相关说明 4 | 5 | 出于安全方面考虑,仓库代码去除了接口定义部分。自学成材,代码仅供参考。 6 | 7 | #### 应用截图 8 | 9 | ![此处输入图片的描述][1] 10 | 11 | #### 下载地址 12 | 13 | http://www.greenuuu.com/pub/update/windows/greendot-windows.zip 14 | 15 | #### 软件介绍 16 | 详情:http://www.greenuuu.com 17 | 18 | [1]: http://www.greenuuu.com/pub/home/img/guide/win2.png -------------------------------------------------------------------------------- /shadowsocks-csharp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shadowsocks-csharp", "shadowsocks-csharp\shadowsocks-csharp.csproj", "{84529DA0-A4B4-4258-A1C6-26E093170C5C}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaterialSkin", "MaterialSkin\MaterialSkin.csproj", "{8EB7611B-68CD-4B8B-987A-11717E2B250C}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x86 = Debug|x86 14 | Release|Any CPU = Release|Any CPU 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {84529DA0-A4B4-4258-A1C6-26E093170C5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {84529DA0-A4B4-4258-A1C6-26E093170C5C}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {84529DA0-A4B4-4258-A1C6-26E093170C5C}.Debug|x86.ActiveCfg = Debug|x86 21 | {84529DA0-A4B4-4258-A1C6-26E093170C5C}.Debug|x86.Build.0 = Debug|x86 22 | {84529DA0-A4B4-4258-A1C6-26E093170C5C}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {84529DA0-A4B4-4258-A1C6-26E093170C5C}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {84529DA0-A4B4-4258-A1C6-26E093170C5C}.Release|x86.ActiveCfg = Release|x86 25 | {84529DA0-A4B4-4258-A1C6-26E093170C5C}.Release|x86.Build.0 = Release|x86 26 | {8EB7611B-68CD-4B8B-987A-11717E2B250C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {8EB7611B-68CD-4B8B-987A-11717E2B250C}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {8EB7611B-68CD-4B8B-987A-11717E2B250C}.Debug|x86.ActiveCfg = Debug|x86 29 | {8EB7611B-68CD-4B8B-987A-11717E2B250C}.Debug|x86.Build.0 = Debug|x86 30 | {8EB7611B-68CD-4B8B-987A-11717E2B250C}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {8EB7611B-68CD-4B8B-987A-11717E2B250C}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {8EB7611B-68CD-4B8B-987A-11717E2B250C}.Release|x86.ActiveCfg = Release|x86 33 | {8EB7611B-68CD-4B8B-987A-11717E2B250C}.Release|x86.Build.0 = Release|x86 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {C0AC34BD-C17F-4E5A-9D96-A9BB6F036613} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Config/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ShadowSocks.Config 8 | { 9 | class Constants 10 | { 11 | public static string DES_KEY = ""; 12 | 13 | //网站根目录 14 | public static string DEFAULT_SEVER_ROOT = ""; 15 | 16 | //用户注册链接 17 | public static string USER_REGISTER_URI = ""; 18 | 19 | //用户找回密码链接 20 | public static string USER_FINDPWD_URI = ""; 21 | 22 | //用户个人中心链接 23 | public static string USER_CENTER_URI = ""; 24 | 25 | //用户充值链接 26 | public static string RECHARGE_URI = ""; 27 | 28 | //用户登录接口 29 | public static string USER_LOGIN_API = ""; 30 | 31 | //用户注销接口 32 | public static string USER_LOGOUT_API = ""; 33 | 34 | //用户信息接口 35 | public static string USER_INFO_API = ""; 36 | 37 | //服务列表接口 38 | public static string SERVER_LIST_API = ""; 39 | 40 | //服务器连接接口 41 | public static string SERVER_CONNECT_API = ""; 42 | 43 | //服务器断开连接接口 44 | public static string SERVER_DISCONNECT_API = ""; 45 | 46 | //更新检测接口 47 | public static string UPDATE_CHECK_API = ""; 48 | 49 | //应用配置接口 50 | public static string APP_CONFIG_API = ""; 51 | 52 | //PAC更新链接 53 | public static string PAC_UPDATE_URI = ""; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/FileManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.IO.Compression; 4 | using System.Text; 5 | 6 | namespace ShadowSocks.Controller 7 | { 8 | public static class FileManager 9 | { 10 | public static bool ByteArrayToFile(string fileName, byte[] content) 11 | { 12 | try 13 | { 14 | using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) 15 | fs.Write(content, 0, content.Length); 16 | return true; 17 | } 18 | catch (Exception ex) 19 | { 20 | Logging.Error(ex); 21 | } 22 | return false; 23 | } 24 | 25 | public static void UncompressFile(string fileName, byte[] content) 26 | { 27 | // Because the uncompressed size of the file is unknown, 28 | // we are using an arbitrary buffer size. 29 | byte[] buffer = new byte[4096]; 30 | int n; 31 | 32 | using(var fs = File.Create(fileName)) 33 | using (var input = new GZipStream(new MemoryStream(content), 34 | CompressionMode.Decompress, false)) 35 | { 36 | while ((n = input.Read(buffer, 0, buffer.Length)) > 0) 37 | { 38 | fs.Write(buffer, 0, n); 39 | } 40 | } 41 | } 42 | 43 | public static string NonExclusiveReadAllText(string path) 44 | { 45 | return NonExclusiveReadAllText(path, Encoding.Default); 46 | } 47 | 48 | public static string NonExclusiveReadAllText(string path, Encoding encoding) 49 | { 50 | try 51 | { 52 | using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 53 | using (var sr = new StreamReader(fs, encoding)) 54 | { 55 | return sr.ReadToEnd(); 56 | } 57 | } 58 | catch (Exception ex) 59 | { 60 | Logging.Error(ex); 61 | throw ex; 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/I18N.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | 6 | namespace ShadowSocks.Controller 7 | { 8 | using ShadowSocks.Properties; 9 | 10 | public static class I18N 11 | { 12 | private static Dictionary _strings = new Dictionary(); 13 | 14 | private static void Init(string res) 15 | { 16 | using (var sr = new StringReader(res)) 17 | { 18 | foreach (var line in sr.NonWhiteSpaceLines()) 19 | { 20 | if (line[0] == '#') 21 | continue; 22 | 23 | var pos = line.IndexOf('='); 24 | if (pos < 1) 25 | continue; 26 | _strings[line.Substring(0, pos)] = line.Substring(pos + 1); 27 | } 28 | } 29 | } 30 | 31 | static I18N() 32 | { 33 | string name = CultureInfo.CurrentCulture.EnglishName; 34 | if (name.StartsWith("Chinese", StringComparison.OrdinalIgnoreCase)) 35 | { 36 | // choose Traditional Chinese only if we get explicit indication 37 | Init(name.Contains("Traditional") 38 | ? Resources.zh_TW 39 | : Resources.zh_CN); 40 | } 41 | else if (name.StartsWith("Japan", StringComparison.OrdinalIgnoreCase)) 42 | { 43 | Init(Resources.ja); 44 | } 45 | } 46 | 47 | public static string GetString(string key) 48 | { 49 | return _strings.ContainsKey(key) 50 | ? _strings[key] 51 | : key; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/Logging.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.IO; 4 | using System.Net.Sockets; 5 | using System.Net; 6 | using System.Diagnostics; 7 | using System.Text; 8 | using ShadowSocks.Util; 9 | 10 | namespace ShadowSocks.Controller 11 | { 12 | public class Logging 13 | { 14 | public static string LogFilePath; 15 | 16 | private static FileStream _fs; 17 | private static StreamWriterWithTimestamp _sw; 18 | 19 | public static bool OpenLogFile() 20 | { 21 | try 22 | { 23 | LogFilePath = Utils.GetTempPath("greendot.log"); 24 | 25 | _fs = new FileStream(LogFilePath, FileMode.Append); 26 | _sw = new StreamWriterWithTimestamp(_fs); 27 | _sw.AutoFlush = true; 28 | Console.SetOut(_sw); 29 | Console.SetError(_sw); 30 | 31 | return true; 32 | } 33 | catch (IOException e) 34 | { 35 | Console.WriteLine(e.ToString()); 36 | return false; 37 | } 38 | } 39 | 40 | private static void WriteToLogFile(object o) 41 | { 42 | try { 43 | Console.WriteLine(o); 44 | } catch(ObjectDisposedException) { 45 | } 46 | } 47 | 48 | public static void Error(object o) 49 | { 50 | WriteToLogFile("[E] " + o); 51 | } 52 | 53 | public static void Info(object o) 54 | { 55 | WriteToLogFile(o); 56 | } 57 | 58 | public static void Clear() { 59 | _sw.Close(); 60 | _sw.Dispose(); 61 | _fs.Close(); 62 | _fs.Dispose(); 63 | File.Delete(LogFilePath); 64 | OpenLogFile(); 65 | } 66 | 67 | [Conditional("DEBUG")] 68 | public static void Debug(object o) 69 | { 70 | WriteToLogFile("[D] " + o); 71 | } 72 | 73 | [Conditional("DEBUG")] 74 | public static void Dump(string tag, byte[] arr, int length) 75 | { 76 | var sb = new StringBuilder($"{Environment.NewLine}{tag}: "); 77 | for (int i = 0; i < length - 1; i++) { 78 | sb.Append($"0x{arr[i]:X2}, "); 79 | } 80 | sb.Append($"0x{arr[length - 1]:X2}"); 81 | sb.Append(Environment.NewLine); 82 | Debug(sb.ToString()); 83 | } 84 | 85 | [Conditional("DEBUG")] 86 | public static void Debug(EndPoint local, EndPoint remote, int len, string header = null, string tailer = null) 87 | { 88 | if (header == null && tailer == null) 89 | Debug($"{local} => {remote} (size={len})"); 90 | else if (header == null && tailer != null) 91 | Debug($"{local} => {remote} (size={len}), {tailer}"); 92 | else if (header != null && tailer == null) 93 | Debug($"{header}: {local} => {remote} (size={len})"); 94 | else 95 | Debug($"{header}: {local} => {remote} (size={len}), {tailer}"); 96 | } 97 | 98 | [Conditional("DEBUG")] 99 | public static void Debug(Socket sock, int len, string header = null, string tailer = null) 100 | { 101 | Debug(sock.LocalEndPoint, sock.RemoteEndPoint, len, header, tailer); 102 | } 103 | 104 | public static void LogUsefulException(Exception e) 105 | { 106 | // just log useful exceptions, not all of them 107 | if (e is SocketException) 108 | { 109 | SocketException se = (SocketException)e; 110 | if (se.SocketErrorCode == SocketError.ConnectionAborted) 111 | { 112 | // closed by browser when sending 113 | // normally happens when download is canceled or a tab is closed before page is loaded 114 | } 115 | else if (se.SocketErrorCode == SocketError.ConnectionReset) 116 | { 117 | // received rst 118 | } 119 | else if (se.SocketErrorCode == SocketError.NotConnected) 120 | { 121 | // The application tried to send or receive data, and the System.Net.Sockets.Socket is not connected. 122 | } 123 | else if (se.SocketErrorCode == SocketError.HostUnreachable) 124 | { 125 | // There is no network route to the specified host. 126 | } 127 | else if (se.SocketErrorCode == SocketError.TimedOut) 128 | { 129 | // The connection attempt timed out, or the connected host has failed to respond. 130 | } 131 | else 132 | { 133 | Info(e); 134 | } 135 | } 136 | else if (e is ObjectDisposedException) 137 | { 138 | } 139 | else if (e is Win32Exception) 140 | { 141 | var ex = (Win32Exception) e; 142 | 143 | // Win32Exception (0x80004005): A 32 bit processes cannot access modules of a 64 bit process. 144 | if ((uint) ex.ErrorCode != 0x80004005) 145 | { 146 | Info(e); 147 | } 148 | } 149 | else 150 | { 151 | Info(e); 152 | } 153 | } 154 | } 155 | 156 | // Simply extended System.IO.StreamWriter for adding timestamp workaround 157 | public class StreamWriterWithTimestamp : StreamWriter 158 | { 159 | public StreamWriterWithTimestamp(Stream stream) : base(stream) 160 | { 161 | } 162 | 163 | private string GetTimestamp() 164 | { 165 | return "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] "; 166 | } 167 | 168 | public override void WriteLine(string value) 169 | { 170 | base.WriteLine(GetTimestamp() + value); 171 | } 172 | 173 | public override void Write(string value) 174 | { 175 | base.Write(GetTimestamp() + value); 176 | } 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/Service/GfwListUpdater.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Text; 6 | 7 | using Newtonsoft.Json; 8 | 9 | using ShadowSocks.Model; 10 | using ShadowSocks.Properties; 11 | using ShadowSocks.Util; 12 | using ShadowSocks.Config; 13 | 14 | namespace ShadowSocks.Controller 15 | { 16 | public class GFWListUpdater 17 | { 18 | public event EventHandler UpdateCompleted; 19 | 20 | public event ErrorEventHandler Error; 21 | 22 | public class ResultEventArgs : EventArgs 23 | { 24 | public bool Success; 25 | 26 | public ResultEventArgs(bool success) 27 | { 28 | this.Success = success; 29 | } 30 | } 31 | 32 | private static readonly IEnumerable IgnoredLineBegins = new[] { '!', '[' }; 33 | private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 34 | { 35 | try 36 | { 37 | File.WriteAllText(Utils.GetTempPath("gfwlist.txt"), e.Result, Encoding.UTF8); 38 | List lines = ParseResult(e.Result); 39 | if (File.Exists(PACServer.USER_RULE_FILE)) 40 | { 41 | string local = FileManager.NonExclusiveReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8); 42 | using (var sr = new StringReader(local)) 43 | { 44 | foreach (var rule in sr.NonWhiteSpaceLines()) 45 | { 46 | if (rule.BeginWithAny(IgnoredLineBegins)) 47 | continue; 48 | lines.Add(rule); 49 | } 50 | } 51 | } 52 | string abpContent; 53 | if (File.Exists(PACServer.USER_ABP_FILE)) 54 | { 55 | abpContent = FileManager.NonExclusiveReadAllText(PACServer.USER_ABP_FILE, Encoding.UTF8); 56 | } 57 | else 58 | { 59 | abpContent = Utils.UnGzip(Resources.abp_js); 60 | } 61 | abpContent = abpContent.Replace("__RULES__", JsonConvert.SerializeObject(lines, Formatting.Indented)); 62 | if (File.Exists(PACServer.PAC_FILE)) 63 | { 64 | string original = FileManager.NonExclusiveReadAllText(PACServer.PAC_FILE, Encoding.UTF8); 65 | if (original == abpContent) 66 | { 67 | UpdateCompleted(this, new ResultEventArgs(false)); 68 | return; 69 | } 70 | } 71 | File.WriteAllText(PACServer.PAC_FILE, abpContent, Encoding.UTF8); 72 | if (UpdateCompleted != null) 73 | { 74 | UpdateCompleted(this, new ResultEventArgs(true)); 75 | } 76 | } 77 | catch (Exception ex) 78 | { 79 | if (Error != null) 80 | { 81 | Error(this, new ErrorEventArgs(ex)); 82 | } 83 | } 84 | } 85 | 86 | public void UpdatePACFromGFWList(Configuration config) 87 | { 88 | string pacUpdateUri = Constants.PAC_UPDATE_URI; 89 | WebClient http = new WebClient(); 90 | http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort); 91 | http.DownloadStringCompleted += http_DownloadStringCompleted; 92 | http.DownloadStringAsync(new Uri(pacUpdateUri)); 93 | } 94 | 95 | public static List ParseResult(string response) 96 | { 97 | byte[] bytes = Convert.FromBase64String(response); 98 | string content = Encoding.ASCII.GetString(bytes); 99 | List valid_lines = new List(); 100 | using (var sr = new StringReader(content)) 101 | { 102 | foreach (var line in sr.NonWhiteSpaceLines()) 103 | { 104 | if (line.BeginWithAny(IgnoredLineBegins)) 105 | continue; 106 | valid_lines.Add(line); 107 | } 108 | } 109 | return valid_lines; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Sockets; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | using ShadowSocks.Model; 10 | using ShadowSocks.Properties; 11 | using ShadowSocks.Util; 12 | using ShadowSocks.Util.ProcessManagement; 13 | 14 | namespace ShadowSocks.Controller 15 | { 16 | class PrivoxyRunner 17 | { 18 | private static int _uid; 19 | private static string _uniqueConfigFile; 20 | private static Job _privoxyJob; 21 | private Process _process; 22 | private int _runningPort; 23 | 24 | static PrivoxyRunner() 25 | { 26 | try 27 | { 28 | _uid = Application.StartupPath.GetHashCode(); // Currently we use ss's StartupPath to identify different Privoxy instance. 29 | _uniqueConfigFile = $"privoxy_{_uid}.conf"; 30 | _privoxyJob = new Job(); 31 | 32 | FileManager.UncompressFile(Utils.GetTempPath("greendot_privoxy.exe"), Resources.privoxy_exe); 33 | FileManager.UncompressFile(Utils.GetTempPath("mgwz.dll"), Resources.mgwz_dll); 34 | } 35 | catch (IOException e) 36 | { 37 | Logging.LogUsefulException(e); 38 | } 39 | } 40 | 41 | public int RunningPort => _runningPort; 42 | 43 | public void Start(Configuration configuration) 44 | { 45 | if (_process == null) 46 | { 47 | Process[] existingPrivoxy = Process.GetProcessesByName("greendot_privoxy"); 48 | foreach (Process p in existingPrivoxy.Where(IsChildProcess)) 49 | { 50 | KillProcess(p); 51 | } 52 | string privoxyConfig = Resources.privoxy_conf; 53 | _runningPort = GetFreePort(); 54 | privoxyConfig = privoxyConfig.Replace("__SOCKS_PORT__", configuration.localPort.ToString()); 55 | privoxyConfig = privoxyConfig.Replace("__PRIVOXY_BIND_PORT__", _runningPort.ToString()); 56 | privoxyConfig = privoxyConfig.Replace("__PRIVOXY_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1"); 57 | FileManager.ByteArrayToFile(Utils.GetTempPath(_uniqueConfigFile), Encoding.UTF8.GetBytes(privoxyConfig)); 58 | 59 | _process = new Process 60 | { 61 | // Configure the process using the StartInfo properties. 62 | StartInfo = 63 | { 64 | FileName = "greendot_privoxy.exe", 65 | Arguments = _uniqueConfigFile, 66 | WorkingDirectory = Utils.GetTempPath(), 67 | WindowStyle = ProcessWindowStyle.Hidden, 68 | UseShellExecute = true, 69 | CreateNoWindow = true 70 | } 71 | }; 72 | _process.Start(); 73 | 74 | /* 75 | * Add this process to job obj associated with this ss process, so that 76 | * when ss exit unexpectedly, this process will be forced killed by system. 77 | */ 78 | _privoxyJob.AddProcess(_process.Handle); 79 | } 80 | } 81 | 82 | public void Stop() 83 | { 84 | if (_process != null) 85 | { 86 | KillProcess(_process); 87 | _process.Dispose(); 88 | _process = null; 89 | } 90 | } 91 | 92 | private static void KillProcess(Process p) 93 | { 94 | try 95 | { 96 | p.CloseMainWindow(); 97 | p.WaitForExit(100); 98 | if (!p.HasExited) 99 | { 100 | p.Kill(); 101 | p.WaitForExit(); 102 | } 103 | } 104 | catch (Exception e) 105 | { 106 | Logging.LogUsefulException(e); 107 | } 108 | } 109 | 110 | /* 111 | * We won't like to kill other ss instances' ss_privoxy.exe. 112 | * This function will check whether the given process is created 113 | * by this process by checking the module path or command line. 114 | * 115 | * Since it's required to put ss in different dirs to run muti instances, 116 | * different instance will create their unique "privoxy_UID.conf" where 117 | * UID is hash of ss's location. 118 | */ 119 | 120 | private static bool IsChildProcess(Process process) 121 | { 122 | try 123 | { 124 | /* 125 | * Under PortableMode, we could identify it by the path of ss_privoxy.exe. 126 | */ 127 | var path = process.MainModule.FileName; 128 | 129 | return Utils.GetTempPath("greendot_privoxy.exe").Equals(path); 130 | 131 | } 132 | catch (Exception ex) 133 | { 134 | /* 135 | * Sometimes Process.GetProcessesByName will return some processes that 136 | * are already dead, and that will cause exceptions here. 137 | * We could simply ignore those exceptions. 138 | */ 139 | Logging.LogUsefulException(ex); 140 | return false; 141 | } 142 | } 143 | 144 | private int GetFreePort() 145 | { 146 | int defaultPort = 8123; 147 | try 148 | { 149 | // TCP stack please do me a favor 150 | TcpListener l = new TcpListener(IPAddress.Loopback, 0); 151 | l.Start(); 152 | var port = ((IPEndPoint)l.LocalEndpoint).Port; 153 | l.Stop(); 154 | return port; 155 | } 156 | catch (Exception e) 157 | { 158 | // in case access denied 159 | Logging.LogUsefulException(e); 160 | return defaultPort; 161 | } 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/Service/Sip003Plugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | using System.Reflection; 7 | using ShadowSocks.Model; 8 | using ShadowSocks.Util.ProcessManagement; 9 | 10 | namespace ShadowSocks.Controller.Service 11 | { 12 | public sealed class Sip003Plugin : IDisposable 13 | { 14 | public IPEndPoint LocalEndPoint { get; private set; } 15 | public int ProcessId => _started ? _pluginProcess.Id : 0; 16 | 17 | private readonly object _startProcessLock = new object(); 18 | private readonly Job _pluginJob; 19 | private readonly Process _pluginProcess; 20 | private bool _started; 21 | private bool _disposed; 22 | 23 | public static Sip003Plugin CreateIfConfigured(Server server) 24 | { 25 | if (server == null) 26 | { 27 | throw new ArgumentNullException(nameof(server)); 28 | } 29 | 30 | if (string.IsNullOrWhiteSpace(server.plugin)) 31 | { 32 | return null; 33 | } 34 | 35 | return new Sip003Plugin(server.plugin, server.plugin_opts, server.server, server.server_port); 36 | } 37 | 38 | private Sip003Plugin(string plugin, string pluginOpts, string serverAddress, int serverPort) 39 | { 40 | if (plugin == null) throw new ArgumentNullException(nameof(plugin)); 41 | if (string.IsNullOrWhiteSpace(serverAddress)) 42 | { 43 | throw new ArgumentException("Value cannot be null or whitespace.", nameof(serverAddress)); 44 | } 45 | if ((ushort)serverPort != serverPort) 46 | { 47 | throw new ArgumentOutOfRangeException("serverPort"); 48 | } 49 | 50 | var appPath = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).LocalPath); 51 | 52 | _pluginProcess = new Process 53 | { 54 | StartInfo = new ProcessStartInfo 55 | { 56 | FileName = plugin, 57 | UseShellExecute = false, 58 | CreateNoWindow = true, 59 | ErrorDialog = false, 60 | WindowStyle = ProcessWindowStyle.Hidden, 61 | WorkingDirectory = appPath ?? Environment.CurrentDirectory, 62 | Environment = 63 | { 64 | ["SS_REMOTE_HOST"] = serverAddress, 65 | ["SS_REMOTE_PORT"] = serverPort.ToString(), 66 | ["SS_PLUGIN_OPTIONS"] = pluginOpts 67 | } 68 | } 69 | }; 70 | 71 | _pluginJob = new Job(); 72 | } 73 | 74 | public bool StartIfNeeded() 75 | { 76 | if (_disposed) 77 | { 78 | throw new ObjectDisposedException(GetType().FullName); 79 | } 80 | 81 | lock (_startProcessLock) 82 | { 83 | if (_started && !_pluginProcess.HasExited) 84 | { 85 | return false; 86 | } 87 | 88 | var localPort = GetNextFreeTcpPort(); 89 | LocalEndPoint = new IPEndPoint(IPAddress.Loopback, localPort); 90 | 91 | _pluginProcess.StartInfo.Environment["SS_LOCAL_HOST"] = LocalEndPoint.Address.ToString(); 92 | _pluginProcess.StartInfo.Environment["SS_LOCAL_PORT"] = LocalEndPoint.Port.ToString(); 93 | _pluginProcess.Start(); 94 | _pluginJob.AddProcess(_pluginProcess.Handle); 95 | _started = true; 96 | } 97 | 98 | return true; 99 | } 100 | 101 | static int GetNextFreeTcpPort() 102 | { 103 | var l = new TcpListener(IPAddress.Loopback, 0); 104 | l.Start(); 105 | int port = ((IPEndPoint)l.LocalEndpoint).Port; 106 | l.Stop(); 107 | return port; 108 | } 109 | 110 | public void Dispose() 111 | { 112 | if (_disposed) 113 | { 114 | return; 115 | } 116 | 117 | try 118 | { 119 | if (!_pluginProcess.HasExited) 120 | { 121 | _pluginProcess.Kill(); 122 | _pluginProcess.WaitForExit(); 123 | } 124 | } 125 | catch (Exception) { } 126 | finally 127 | { 128 | try 129 | { 130 | _pluginProcess.Dispose(); 131 | _pluginJob.Dispose(); 132 | } 133 | catch (Exception) { } 134 | 135 | _disposed = true; 136 | } 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/Service/UpdateChecker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Text.RegularExpressions; 5 | using Newtonsoft.Json.Linq; 6 | using ShadowSocks.Model; 7 | using ShadowSocks.Util; 8 | using ShadowSocks.Config; 9 | using ShadowSocks.Extensions; 10 | 11 | namespace ShadowSocks.Controller 12 | { 13 | public class UpdateChecker 14 | { 15 | private const string UserAgent = "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36"; 16 | 17 | private Configuration config; 18 | public bool NewVersionFound; 19 | public string LatestVersionNumber; 20 | public string LatestVersionSuffix; 21 | public string LatestVersionName; 22 | public string LatestVersionURL; 23 | public string LatestVersionLocalName; 24 | public event EventHandler CheckUpdateCompleted; 25 | 26 | public static string Version; 27 | 28 | private class CheckUpdateTimer : System.Timers.Timer 29 | { 30 | public Configuration config; 31 | 32 | public CheckUpdateTimer(int p) : base(p) 33 | { 34 | } 35 | } 36 | 37 | public void CheckUpdate(Configuration config, int delay) 38 | { 39 | CheckUpdateTimer timer = new CheckUpdateTimer(delay); 40 | timer.AutoReset = false; 41 | timer.Elapsed += Timer_Elapsed; 42 | timer.config = config; 43 | timer.Enabled = true; 44 | } 45 | 46 | private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 47 | { 48 | CheckUpdateTimer timer = (CheckUpdateTimer)sender; 49 | Configuration config = timer.config; 50 | timer.Elapsed -= Timer_Elapsed; 51 | timer.Enabled = false; 52 | timer.Dispose(); 53 | CheckUpdate(config); 54 | } 55 | 56 | public void CheckUpdate(Configuration config) 57 | { 58 | this.config = config; 59 | try 60 | { 61 | Version = Util.Utils.getCurrentVersion(); 62 | string checkUri = Constants.DEFAULT_SEVER_ROOT + Constants.UPDATE_CHECK_API + "?device=windows" + "&version=" + Version; 63 | 64 | Logging.Debug("Checking updates..."); 65 | WebClient http = CreateWebClient(); 66 | http.DownloadStringCompleted += http_DownloadStringCompleted; 67 | http.DownloadStringAsync(new Uri(checkUri)); 68 | } 69 | catch (Exception ex) 70 | { 71 | Logging.LogUsefulException(ex); 72 | } 73 | } 74 | 75 | private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 76 | { 77 | try 78 | { 79 | string response = e.Result; 80 | JObject result = JObject.Parse(response); 81 | if (result.ok() && result.content() != null) 82 | { 83 | var content = result.content(); 84 | var version = content.version; 85 | var downloadLink = content.downloadlink; 86 | var name = content.name; 87 | if (version != null && downloadLink != null && name != null) 88 | { 89 | NewVersionFound = true; 90 | LatestVersionNumber = (string)version; 91 | LatestVersionURL = (string)downloadLink; 92 | LatestVersionName = (string)name; 93 | startDownload(); 94 | } 95 | } 96 | else 97 | { 98 | Logging.Debug("No update is available"); 99 | if (CheckUpdateCompleted != null) 100 | { 101 | CheckUpdateCompleted(this, new EventArgs()); 102 | } 103 | } 104 | } 105 | catch (Exception ex) 106 | { 107 | Logging.LogUsefulException(ex); 108 | } 109 | } 110 | 111 | private void startDownload() 112 | { 113 | try 114 | { 115 | LatestVersionLocalName = Utils.GetTempPath(LatestVersionName); 116 | WebClient http = CreateWebClient(); 117 | http.DownloadFileCompleted += Http_DownloadFileCompleted; 118 | http.DownloadFileAsync(new Uri(LatestVersionURL), LatestVersionLocalName); 119 | } 120 | catch (Exception ex) 121 | { 122 | Logging.LogUsefulException(ex); 123 | } 124 | } 125 | 126 | private void Http_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) 127 | { 128 | try 129 | { 130 | if (e.Error != null) 131 | { 132 | Logging.LogUsefulException(e.Error); 133 | return; 134 | } 135 | Logging.Debug($"New version {LatestVersionNumber}{LatestVersionSuffix} found: {LatestVersionLocalName}"); 136 | if (CheckUpdateCompleted != null) 137 | { 138 | CheckUpdateCompleted(this, new EventArgs()); 139 | } 140 | } 141 | catch (Exception ex) 142 | { 143 | Logging.LogUsefulException(ex); 144 | } 145 | } 146 | 147 | private WebClient CreateWebClient() 148 | { 149 | WebClient http = new WebClient(); 150 | http.Headers.Add("User-Agent", UserAgent); 151 | //http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort); 152 | return http; 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/Strategy/BalancingStrategy.cs: -------------------------------------------------------------------------------- 1 | using ShadowSocks.Controller; 2 | using ShadowSocks.Model; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Net; 6 | using System.Text; 7 | 8 | namespace ShadowSocks.Controller.Strategy 9 | { 10 | class BalancingStrategy : IStrategy 11 | { 12 | ShadowSocksController _controller; 13 | Random _random; 14 | 15 | public BalancingStrategy(ShadowSocksController controller) 16 | { 17 | _controller = controller; 18 | _random = new Random(); 19 | } 20 | 21 | public string Name 22 | { 23 | get { return I18N.GetString("Load Balance"); } 24 | } 25 | 26 | public string ID 27 | { 28 | get { return "com.greendot.strategy.balancing"; } 29 | } 30 | 31 | public void ReloadServers() 32 | { 33 | // do nothing 34 | } 35 | 36 | public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint, EndPoint destEndPoint) 37 | { 38 | var configs = _controller.GetCurrentConfiguration().configs; 39 | int index; 40 | if (type == IStrategyCallerType.TCP) 41 | { 42 | index = _random.Next(); 43 | } 44 | else 45 | { 46 | index = localIPEndPoint.GetHashCode(); 47 | } 48 | return configs[index % configs.Count]; 49 | } 50 | 51 | public void UpdateLatency(Model.Server server, TimeSpan latency) 52 | { 53 | // do nothing 54 | } 55 | 56 | public void UpdateLastRead(Model.Server server) 57 | { 58 | // do nothing 59 | } 60 | 61 | public void UpdateLastWrite(Model.Server server) 62 | { 63 | // do nothing 64 | } 65 | 66 | public void SetFailure(Model.Server server) 67 | { 68 | // do nothing 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/Strategy/IStrategy.cs: -------------------------------------------------------------------------------- 1 | using ShadowSocks.Model; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Net; 5 | using System.Text; 6 | 7 | namespace ShadowSocks.Controller.Strategy 8 | { 9 | public enum IStrategyCallerType 10 | { 11 | TCP, 12 | UDP 13 | } 14 | 15 | /* 16 | * IStrategy 17 | * 18 | * Subclasses must be thread-safe 19 | */ 20 | public interface IStrategy 21 | { 22 | string Name { get; } 23 | 24 | string ID { get; } 25 | 26 | /* 27 | * Called when servers need to be reloaded, i.e. new configuration saved 28 | */ 29 | void ReloadServers(); 30 | 31 | /* 32 | * Get a new server to use in TCPRelay or UDPRelay 33 | */ 34 | Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint, EndPoint destEndPoint); 35 | 36 | /* 37 | * TCPRelay will call this when latency of a server detected 38 | */ 39 | void UpdateLatency(Server server, TimeSpan latency); 40 | 41 | /* 42 | * TCPRelay will call this when reading from a server 43 | */ 44 | void UpdateLastRead(Server server); 45 | 46 | /* 47 | * TCPRelay will call this when writing to a server 48 | */ 49 | void UpdateLastWrite(Server server); 50 | 51 | /* 52 | * TCPRelay will call this when fatal failure detected 53 | */ 54 | void SetFailure(Server server); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/Strategy/StrategyManager.cs: -------------------------------------------------------------------------------- 1 | using ShadowSocks.Controller; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace ShadowSocks.Controller.Strategy 7 | { 8 | class StrategyManager 9 | { 10 | List _strategies; 11 | public StrategyManager(ShadowSocksController controller) 12 | { 13 | _strategies = new List(); 14 | _strategies.Add(new BalancingStrategy(controller)); 15 | _strategies.Add(new HighAvailabilityStrategy(controller)); 16 | _strategies.Add(new StatisticsStrategy(controller)); 17 | // TODO: load DLL plugins 18 | } 19 | public IList GetStrategies() 20 | { 21 | return _strategies; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/System/AutoStartup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Windows.Forms; 4 | using Microsoft.Win32; 5 | using ShadowSocks.Util; 6 | 7 | namespace ShadowSocks.Controller 8 | { 9 | static class AutoStartup 10 | { 11 | // Don't use Application.ExecutablePath 12 | // see https://stackoverflow.com/questions/12945805/odd-c-sharp-path-issue 13 | private static readonly string ExecutablePath = Assembly.GetEntryAssembly().Location; 14 | 15 | private static string Key = "greendot_" + Application.StartupPath.GetHashCode(); 16 | 17 | public static bool Set(bool enabled) 18 | { 19 | RegistryKey runKey = null; 20 | try 21 | { 22 | runKey = Utils.OpenRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true); 23 | if ( runKey == null ) { 24 | Logging.Error( @"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run" ); 25 | return false; 26 | } 27 | if (enabled) 28 | { 29 | runKey.SetValue(Key, ExecutablePath); 30 | } 31 | else 32 | { 33 | runKey.DeleteValue(Key); 34 | } 35 | return true; 36 | } 37 | catch (Exception e) 38 | { 39 | Logging.LogUsefulException(e); 40 | return false; 41 | } 42 | finally 43 | { 44 | if (runKey != null) 45 | { 46 | try { 47 | runKey.Close(); 48 | runKey.Dispose(); 49 | } catch (Exception e) 50 | { Logging.LogUsefulException(e); } 51 | } 52 | } 53 | } 54 | 55 | public static bool Check() 56 | { 57 | RegistryKey runKey = null; 58 | try 59 | { 60 | runKey = Utils.OpenRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true); 61 | if (runKey == null) { 62 | Logging.Error(@"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run"); 63 | return false; 64 | } 65 | string[] runList = runKey.GetValueNames(); 66 | foreach (string item in runList) 67 | { 68 | if (item.Equals(Key, StringComparison.OrdinalIgnoreCase)) 69 | return true; 70 | else if (item.Equals("GreenDot", StringComparison.OrdinalIgnoreCase)) // Compatibility with older versions 71 | { 72 | string value = Convert.ToString(runKey.GetValue(item)); 73 | if (ExecutablePath.Equals(value, StringComparison.OrdinalIgnoreCase)) 74 | { 75 | runKey.DeleteValue(item); 76 | runKey.SetValue(Key, ExecutablePath); 77 | return true; 78 | } 79 | } 80 | } 81 | return false; 82 | } 83 | catch (Exception e) 84 | { 85 | Logging.LogUsefulException(e); 86 | return false; 87 | } 88 | finally 89 | { 90 | if (runKey != null) 91 | { 92 | try { 93 | runKey.Close(); 94 | runKey.Dispose(); 95 | } catch (Exception e) 96 | { Logging.LogUsefulException(e); } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/System/Hotkeys/HotkeyCallbacks.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace ShadowSocks.Controller.Hotkeys 5 | { 6 | public class HotkeyCallbacks 7 | { 8 | 9 | public static void InitInstance(ShadowSocksController controller) 10 | { 11 | if (Instance != null) 12 | { 13 | return; 14 | } 15 | 16 | Instance = new HotkeyCallbacks(controller); 17 | } 18 | 19 | /// 20 | /// Create hotkey callback handler delegate based on callback name 21 | /// 22 | /// 23 | /// 24 | public static Delegate GetCallback(string methodname) 25 | { 26 | if (methodname.IsNullOrEmpty()) throw new ArgumentException(nameof(methodname)); 27 | MethodInfo dynMethod = typeof(HotkeyCallbacks).GetMethod(methodname, 28 | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase); 29 | return dynMethod == null ? null : Delegate.CreateDelegate(typeof(HotKeys.HotKeyCallBackHandler), Instance, dynMethod); 30 | } 31 | 32 | #region Singleton 33 | 34 | private static HotkeyCallbacks Instance { get; set; } 35 | 36 | private readonly ShadowSocksController _controller; 37 | 38 | private HotkeyCallbacks(ShadowSocksController controller) 39 | { 40 | _controller = controller; 41 | } 42 | 43 | #endregion 44 | 45 | #region Callbacks 46 | 47 | private void SwitchSystemProxyCallback() 48 | { 49 | bool enabled = _controller.GetConfigurationCopy().enabled; 50 | _controller.ToggleEnable(!enabled); 51 | } 52 | 53 | private void SwitchProxyModeCallback() 54 | { 55 | var config = _controller.GetConfigurationCopy(); 56 | if (config.enabled == false) return; 57 | var currStatus = config.global; 58 | _controller.ToggleGlobal(!currStatus); 59 | } 60 | 61 | private void SwitchAllowLanCallback() 62 | { 63 | var status = _controller.GetConfigurationCopy().shareOverLan; 64 | _controller.ToggleShareOverLAN(!status); 65 | } 66 | 67 | private void ShowLogsCallback() 68 | { 69 | //Program.MenuController.ShowLogForm_HotKey(); 70 | } 71 | 72 | private void ServerMoveUpCallback() 73 | { 74 | int currIndex; 75 | int serverCount; 76 | GetCurrServerInfo(out currIndex, out serverCount); 77 | if (currIndex - 1 < 0) 78 | { 79 | // revert to last server 80 | currIndex = serverCount - 1; 81 | } 82 | else 83 | { 84 | currIndex -= 1; 85 | } 86 | _controller.SelectServerIndex(currIndex); 87 | } 88 | 89 | private void ServerMoveDownCallback() 90 | { 91 | int currIndex; 92 | int serverCount; 93 | GetCurrServerInfo(out currIndex, out serverCount); 94 | if (currIndex + 1 == serverCount) 95 | { 96 | // revert to first server 97 | currIndex = 0; 98 | } 99 | else 100 | { 101 | currIndex += 1; 102 | } 103 | _controller.SelectServerIndex(currIndex); 104 | } 105 | 106 | private void GetCurrServerInfo(out int currIndex, out int serverCount) 107 | { 108 | var currConfig = _controller.GetCurrentConfiguration(); 109 | currIndex = currConfig.index; 110 | serverCount = currConfig.configs.Count; 111 | } 112 | 113 | #endregion 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/System/Hotkeys/Hotkeys.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Windows.Input; 6 | using GlobalHotKey; 7 | 8 | namespace ShadowSocks.Controller.Hotkeys 9 | { 10 | public static class HotKeys 11 | { 12 | private static HotKeyManager _hotKeyManager; 13 | 14 | public delegate void HotKeyCallBackHandler(); 15 | // map key and corresponding handler function 16 | private static Dictionary _keymap = new Dictionary(); 17 | 18 | public static void Init(ShadowSocksController controller) 19 | { 20 | _hotKeyManager = new HotKeyManager(); 21 | _hotKeyManager.KeyPressed += HotKeyManagerPressed; 22 | 23 | HotkeyCallbacks.InitInstance(controller); 24 | } 25 | 26 | public static void Destroy() 27 | { 28 | _hotKeyManager.KeyPressed -= HotKeyManagerPressed; 29 | _hotKeyManager.Dispose(); 30 | } 31 | 32 | private static void HotKeyManagerPressed(object sender, KeyPressedEventArgs e) 33 | { 34 | var hotkey = e.HotKey; 35 | HotKeyCallBackHandler callback; 36 | if (_keymap.TryGetValue(hotkey, out callback)) 37 | callback(); 38 | } 39 | 40 | public static bool IsHotkeyExists( HotKey hotKey ) 41 | { 42 | if (hotKey == null) throw new ArgumentNullException(nameof(hotKey)); 43 | return _keymap.Any( v => v.Key.Equals( hotKey ) ); 44 | } 45 | 46 | public static bool IsCallbackExists( HotKeyCallBackHandler cb, out HotKey hotkey) 47 | { 48 | if (cb == null) throw new ArgumentNullException(nameof(cb)); 49 | try 50 | { 51 | var key = _keymap.First(x => x.Value == cb).Key; 52 | hotkey = key; 53 | return true; 54 | } 55 | catch (InvalidOperationException) 56 | { 57 | // not found 58 | hotkey = null; 59 | return false; 60 | } 61 | } 62 | public static string HotKey2Str( HotKey key ) 63 | { 64 | if (key == null) throw new ArgumentNullException(nameof(key)); 65 | return HotKey2Str( key.Key, key.Modifiers ); 66 | } 67 | 68 | public static string HotKey2Str( Key key, ModifierKeys modifier ) 69 | { 70 | if (!Enum.IsDefined(typeof(Key), key)) 71 | throw new InvalidEnumArgumentException(nameof(key), (int) key, typeof(Key)); 72 | try 73 | { 74 | ModifierKeysConverter mkc = new ModifierKeysConverter(); 75 | var keyStr = Enum.GetName(typeof(Key), key); 76 | var modifierStr = mkc.ConvertToInvariantString(modifier); 77 | 78 | return $"{modifierStr}+{keyStr}"; 79 | } 80 | catch (NotSupportedException) 81 | { 82 | // converter exception 83 | return null; 84 | } 85 | } 86 | 87 | public static HotKey Str2HotKey(string s) 88 | { 89 | try 90 | { 91 | if (s.IsNullOrEmpty()) return null; 92 | int offset = s.LastIndexOf("+", StringComparison.OrdinalIgnoreCase); 93 | if (offset <= 0) return null; 94 | string modifierStr = s.Substring(0, offset).Trim(); 95 | string keyStr = s.Substring(offset + 1).Trim(); 96 | 97 | KeyConverter kc = new KeyConverter(); 98 | ModifierKeysConverter mkc = new ModifierKeysConverter(); 99 | Key key = (Key) kc.ConvertFrom(keyStr.ToUpper()); 100 | ModifierKeys modifier = (ModifierKeys) mkc.ConvertFrom(modifierStr.ToUpper()); 101 | 102 | return new HotKey(key, modifier); 103 | } 104 | catch (NotSupportedException) 105 | { 106 | // converter exception 107 | return null; 108 | } 109 | catch (NullReferenceException) 110 | { 111 | return null; 112 | } 113 | } 114 | 115 | public static bool Regist( HotKey key, HotKeyCallBackHandler callBack ) 116 | { 117 | if (key == null) 118 | throw new ArgumentNullException(nameof(key)); 119 | if (callBack == null) 120 | throw new ArgumentNullException(nameof(callBack)); 121 | try 122 | { 123 | _hotKeyManager.Register(key); 124 | _keymap[key] = callBack; 125 | return true; 126 | } 127 | catch (ArgumentException) 128 | { 129 | // already called this method with the specific hotkey 130 | // return success silently 131 | return true; 132 | } 133 | catch (Win32Exception) 134 | { 135 | // this hotkey already registered by other programs 136 | // notify user to change key 137 | return false; 138 | } 139 | } 140 | 141 | public static bool Regist(Key key, ModifierKeys modifiers, HotKeyCallBackHandler callBack) 142 | { 143 | if (!Enum.IsDefined(typeof(Key), key)) 144 | throw new InvalidEnumArgumentException(nameof(key), (int) key, typeof(Key)); 145 | try 146 | { 147 | var hotkey = _hotKeyManager.Register(key, modifiers); 148 | _keymap[hotkey] = callBack; 149 | return true; 150 | } 151 | catch (ArgumentException) 152 | { 153 | // already called this method with the specific hotkey 154 | // return success silently 155 | return true; 156 | } 157 | catch (Win32Exception) 158 | { 159 | // already registered by other programs 160 | // notify user to change key 161 | return false; 162 | } 163 | } 164 | 165 | public static void UnRegist(HotKey key) 166 | { 167 | if (key == null) 168 | throw new ArgumentNullException(nameof(key)); 169 | _hotKeyManager.Unregister(key); 170 | if(_keymap.ContainsKey(key)) 171 | _keymap.Remove(key); 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Controller/System/SystemProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ShadowSocks.Model; 3 | using ShadowSocks.Util.SystemProxy; 4 | 5 | namespace ShadowSocks.Controller 6 | { 7 | public static class SystemProxy 8 | { 9 | private static string GetTimestamp(DateTime value) 10 | { 11 | return value.ToString("yyyyMMddHHmmssfff"); 12 | } 13 | 14 | public static void Disable() 15 | { 16 | WinINet.SetIEProxy(false, false, "", ""); 17 | } 18 | 19 | public static void Update(Configuration config, bool forceDisable, PACServer pacSrv) 20 | { 21 | bool global = config.global; 22 | bool enabled = config.enabled; 23 | 24 | if (forceDisable) 25 | { 26 | enabled = false; 27 | } 28 | 29 | try 30 | { 31 | if (enabled) 32 | { 33 | if (global) 34 | { 35 | Sysproxy.SetIEProxy(true, true, "127.0.0.1:" + config.localPort.ToString(), null); 36 | } 37 | else 38 | { 39 | string pacUrl; 40 | if (config.useOnlinePac && !config.pacUrl.IsNullOrEmpty()) 41 | { 42 | pacUrl = config.pacUrl; 43 | } 44 | else 45 | { 46 | pacUrl = pacSrv.PacUrl; 47 | } 48 | Sysproxy.SetIEProxy(true, false, null, pacUrl); 49 | } 50 | } 51 | else 52 | { 53 | Sysproxy.SetIEProxy(false, false, null, null); 54 | } 55 | } 56 | catch (ProxyException ex) 57 | { 58 | Logging.LogUsefulException(ex); 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Data/abp.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Data/abp.js.gz -------------------------------------------------------------------------------- /shadowsocks-csharp/Data/libsscrypto.dll.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Data/libsscrypto.dll.gz -------------------------------------------------------------------------------- /shadowsocks-csharp/Data/mgwz.dll.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Data/mgwz.dll.gz -------------------------------------------------------------------------------- /shadowsocks-csharp/Data/privoxy.exe.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Data/privoxy.exe.gz -------------------------------------------------------------------------------- /shadowsocks-csharp/Data/privoxy_conf.txt: -------------------------------------------------------------------------------- 1 | listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ 2 | toggle 0 3 | logfile greendot_privoxy.log 4 | show-on-task-bar 0 5 | activity-animation 0 6 | forward-socks5 / 127.0.0.1:__SOCKS_PORT__ . 7 | hide-console 8 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Data/proxy.pac.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Data/proxy.pac.txt.gz -------------------------------------------------------------------------------- /shadowsocks-csharp/Data/sysproxy.exe.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Data/sysproxy.exe.gz -------------------------------------------------------------------------------- /shadowsocks-csharp/Data/sysproxy64.exe.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Data/sysproxy64.exe.gz -------------------------------------------------------------------------------- /shadowsocks-csharp/Data/user-rule.txt: -------------------------------------------------------------------------------- 1 | ! Put user rules line by line in this file. 2 | ! See https://adblockplus.org/en/filter-cheatsheet 3 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using ShadowSocks.Controller; 5 | using ShadowSocks.Encryption.Exception; 6 | 7 | namespace ShadowSocks.Encryption.AEAD 8 | { 9 | public class AEADSodiumEncryptor 10 | : AEADEncryptor, IDisposable 11 | { 12 | private const int CIPHER_CHACHA20IETFPOLY1305 = 1; 13 | private const int CIPHER_AES256GCM = 2; 14 | 15 | private byte[] _sodiumEncSubkey; 16 | private byte[] _sodiumDecSubkey; 17 | 18 | public AEADSodiumEncryptor(string method, string password) 19 | : base(method, password) 20 | { 21 | _sodiumEncSubkey = new byte[keyLen]; 22 | _sodiumDecSubkey = new byte[keyLen]; 23 | } 24 | 25 | private static Dictionary _ciphers = new Dictionary 26 | { 27 | {"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)}, 28 | {"aes-256-gcm", new EncryptorInfo(32, 32, 12, 16, CIPHER_AES256GCM)}, 29 | }; 30 | 31 | public static List SupportedCiphers() 32 | { 33 | return new List(_ciphers.Keys); 34 | } 35 | 36 | protected override Dictionary getCiphers() 37 | { 38 | return _ciphers; 39 | } 40 | 41 | public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) 42 | { 43 | base.InitCipher(salt, isEncrypt, isUdp); 44 | DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey, 45 | isEncrypt ? _sodiumEncSubkey : _sodiumDecSubkey); 46 | } 47 | 48 | 49 | public override int cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) 50 | { 51 | Debug.Assert(_sodiumEncSubkey != null); 52 | // buf: all plaintext 53 | // outbuf: ciphertext + tag 54 | int ret; 55 | ulong encClen = 0; 56 | Logging.Dump("_encNonce before enc", _encNonce, nonceLen); 57 | Logging.Dump("_sodiumEncSubkey", _sodiumEncSubkey, keyLen); 58 | Logging.Dump("before cipherEncrypt: plain", plaintext, (int) plen); 59 | switch (_cipher) 60 | { 61 | case CIPHER_CHACHA20IETFPOLY1305: 62 | ret = Sodium.crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext, ref encClen, 63 | plaintext, (ulong) plen, 64 | null, 0, 65 | null, _encNonce, 66 | _sodiumEncSubkey); 67 | break; 68 | case CIPHER_AES256GCM: 69 | ret = Sodium.crypto_aead_aes256gcm_encrypt(ciphertext, ref encClen, 70 | plaintext, (ulong)plen, 71 | null, 0, 72 | null, _encNonce, 73 | _sodiumEncSubkey); 74 | break; 75 | default: 76 | throw new System.Exception("not implemented"); 77 | } 78 | if (ret != 0) throw new CryptoErrorException(); 79 | Logging.Dump("after cipherEncrypt: cipher", ciphertext, (int) encClen); 80 | clen = (uint) encClen; 81 | return ret; 82 | } 83 | 84 | public override int cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) 85 | { 86 | Debug.Assert(_sodiumDecSubkey != null); 87 | // buf: ciphertext + tag 88 | // outbuf: plaintext 89 | int ret; 90 | ulong decPlen = 0; 91 | Logging.Dump("_decNonce before dec", _decNonce, nonceLen); 92 | Logging.Dump("_sodiumDecSubkey", _sodiumDecSubkey, keyLen); 93 | Logging.Dump("before cipherDecrypt: cipher", ciphertext, (int) clen); 94 | switch (_cipher) 95 | { 96 | case CIPHER_CHACHA20IETFPOLY1305: 97 | ret = Sodium.crypto_aead_chacha20poly1305_ietf_decrypt(plaintext, ref decPlen, 98 | null, 99 | ciphertext, (ulong) clen, 100 | null, 0, 101 | _decNonce, _sodiumDecSubkey); 102 | break; 103 | case CIPHER_AES256GCM: 104 | ret = Sodium.crypto_aead_aes256gcm_decrypt(plaintext, ref decPlen, 105 | null, 106 | ciphertext, (ulong)clen, 107 | null, 0, 108 | _decNonce, _sodiumDecSubkey); 109 | break; 110 | default: 111 | throw new System.Exception("not implemented"); 112 | } 113 | 114 | if (ret != 0) throw new CryptoErrorException(); 115 | Logging.Dump("after cipherDecrypt: plain", plaintext, (int) decPlen); 116 | plen = (uint) decPlen; 117 | return ret; 118 | } 119 | 120 | public override void Dispose() 121 | { 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/DES.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | using System.Security.Cryptography; 4 | using System.IO; 5 | using System.Text; 6 | using ShadowSocks.Config; 7 | 8 | namespace ShadowSocks.Encryption { 9 | 10 | public class DES 11 | { 12 | private static byte[] DESIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; 13 | 14 | public static string DESEnCode(string pToEncrypt) 15 | { 16 | DESCryptoServiceProvider des = new DESCryptoServiceProvider(); 17 | byte[] inputByteArray = Encoding.GetEncoding("UTF-8").GetBytes(pToEncrypt); 18 | 19 | des.Key = ASCIIEncoding.ASCII.GetBytes(Constants.DES_KEY); 20 | des.IV = ASCIIEncoding.ASCII.GetBytes(Constants.DES_KEY); 21 | MemoryStream ms = new MemoryStream(); 22 | CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); 23 | 24 | cs.Write(inputByteArray, 0, inputByteArray.Length); 25 | cs.FlushFinalBlock(); 26 | 27 | StringBuilder ret = new StringBuilder(); 28 | foreach (byte b in ms.ToArray()) 29 | { 30 | ret.AppendFormat("{0:X2}", b); 31 | } 32 | ret.ToString(); 33 | return ret.ToString(); 34 | } 35 | 36 | public static string DESDeCode(string pToDecrypt) 37 | { 38 | DESCryptoServiceProvider des = new DESCryptoServiceProvider(); 39 | byte[] inputByteArray = new byte[pToDecrypt.Length / 2]; 40 | for (int x = 0; x < pToDecrypt.Length / 2; x++) 41 | { 42 | int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16)); 43 | inputByteArray[x] = (byte)i; 44 | } 45 | 46 | des.Key = ASCIIEncoding.ASCII.GetBytes(Constants.DES_KEY); 47 | des.IV = ASCIIEncoding.ASCII.GetBytes(Constants.DES_KEY); 48 | MemoryStream ms = new MemoryStream(); 49 | CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write); 50 | cs.Write(inputByteArray, 0, inputByteArray.Length); 51 | cs.FlushFinalBlock(); 52 | 53 | StringBuilder ret = new StringBuilder(); 54 | 55 | return Encoding.Default.GetString(ms.ToArray()); 56 | } 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/EncryptorBase.cs: -------------------------------------------------------------------------------- 1 | namespace ShadowSocks.Encryption 2 | { 3 | public class EncryptorInfo 4 | { 5 | public int KeySize; 6 | public int IvSize; 7 | public int SaltSize; 8 | public int TagSize; 9 | public int NonceSize; 10 | public int Type; 11 | public string InnerLibName; 12 | 13 | // For those who make use of internal crypto method name 14 | // e.g. mbed TLS 15 | 16 | #region Stream ciphers 17 | 18 | public EncryptorInfo(string innerLibName, int keySize, int ivSize, int type) 19 | { 20 | this.KeySize = keySize; 21 | this.IvSize = ivSize; 22 | this.Type = type; 23 | this.InnerLibName = innerLibName; 24 | } 25 | 26 | public EncryptorInfo(int keySize, int ivSize, int type) 27 | { 28 | this.KeySize = keySize; 29 | this.IvSize = ivSize; 30 | this.Type = type; 31 | this.InnerLibName = string.Empty; 32 | } 33 | 34 | #endregion 35 | 36 | #region AEAD ciphers 37 | 38 | public EncryptorInfo(string innerLibName, int keySize, int saltSize, int nonceSize, int tagSize, int type) 39 | { 40 | this.KeySize = keySize; 41 | this.SaltSize = saltSize; 42 | this.NonceSize = nonceSize; 43 | this.TagSize = tagSize; 44 | this.Type = type; 45 | this.InnerLibName = innerLibName; 46 | } 47 | 48 | public EncryptorInfo(int keySize, int saltSize, int nonceSize, int tagSize, int type) 49 | { 50 | this.KeySize = keySize; 51 | this.SaltSize = saltSize; 52 | this.NonceSize = nonceSize; 53 | this.TagSize = tagSize; 54 | this.Type = type; 55 | this.InnerLibName = string.Empty; 56 | } 57 | 58 | #endregion 59 | } 60 | 61 | public abstract class EncryptorBase 62 | : IEncryptor 63 | { 64 | public const int MAX_INPUT_SIZE = 32768; 65 | 66 | public const int MAX_DOMAIN_LEN = 255; 67 | public const int ADDR_PORT_LEN = 2; 68 | public const int ADDR_ATYP_LEN = 1; 69 | 70 | public const int ATYP_IPv4 = 0x01; 71 | public const int ATYP_DOMAIN = 0x03; 72 | public const int ATYP_IPv6 = 0x04; 73 | 74 | public const int MD5_LEN = 16; 75 | 76 | protected EncryptorBase(string method, string password) 77 | { 78 | Method = method; 79 | Password = password; 80 | } 81 | 82 | protected string Method; 83 | protected string Password; 84 | 85 | public abstract void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength); 86 | 87 | public abstract void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength); 88 | 89 | public abstract void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength); 90 | 91 | public abstract void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength); 92 | 93 | public abstract void Dispose(); 94 | 95 | public int AddrBufLength { get; set; } = - 1; 96 | } 97 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/EncryptorFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using ShadowSocks.Encryption.AEAD; 5 | using ShadowSocks.Encryption.Stream; 6 | 7 | namespace ShadowSocks.Encryption 8 | { 9 | public static class EncryptorFactory 10 | { 11 | private static Dictionary _registeredEncryptors = new Dictionary(); 12 | 13 | private static readonly Type[] ConstructorTypes = {typeof(string), typeof(string)}; 14 | 15 | static EncryptorFactory() 16 | { 17 | var AEADMbedTLSEncryptorSupportedCiphers = AEADMbedTLSEncryptor.SupportedCiphers(); 18 | var AEADSodiumEncryptorSupportedCiphers = AEADSodiumEncryptor.SupportedCiphers(); 19 | if (Sodium.AES256GCMAvailable) 20 | { 21 | // prefer to aes-256-gcm in libsodium 22 | AEADMbedTLSEncryptorSupportedCiphers.Remove("aes-256-gcm"); 23 | } 24 | else 25 | { 26 | AEADSodiumEncryptorSupportedCiphers.Remove("aes-256-gcm"); 27 | } 28 | 29 | foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers()) 30 | { 31 | _registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor)); 32 | } 33 | foreach (string method in StreamSodiumEncryptor.SupportedCiphers()) 34 | { 35 | _registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor)); 36 | } 37 | foreach (string method in AEADMbedTLSEncryptorSupportedCiphers) 38 | { 39 | _registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor)); 40 | } 41 | foreach (string method in AEADSodiumEncryptorSupportedCiphers) 42 | { 43 | _registeredEncryptors.Add(method, typeof(AEADSodiumEncryptor)); 44 | } 45 | } 46 | 47 | public static IEncryptor GetEncryptor(string method, string password) 48 | { 49 | if (method.IsNullOrEmpty()) 50 | { 51 | method = "aes-256-cfb"; 52 | } 53 | method = method.ToLowerInvariant(); 54 | Type t = _registeredEncryptors[method]; 55 | ConstructorInfo c = t.GetConstructor(ConstructorTypes); 56 | if (c == null) throw new System.Exception("Invalid ctor"); 57 | IEncryptor result = (IEncryptor) c.Invoke(new object[] {method, password}); 58 | return result; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/Exception/CryptoException.cs: -------------------------------------------------------------------------------- 1 | namespace ShadowSocks.Encryption.Exception 2 | { 3 | public class CryptoErrorException : System.Exception 4 | { 5 | public CryptoErrorException() 6 | { 7 | } 8 | 9 | public CryptoErrorException(string msg) : base(msg) 10 | { 11 | } 12 | 13 | public CryptoErrorException(string message, System.Exception innerException) : base(message, innerException) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/IEncryptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ShadowSocks.Encryption 4 | { 5 | public interface IEncryptor : IDisposable 6 | { 7 | /* length == -1 means not used */ 8 | int AddrBufLength { set; get; } 9 | void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength); 10 | void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength); 11 | void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength); 12 | void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/MbedTLS.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.InteropServices; 4 | using ShadowSocks.Controller; 5 | using ShadowSocks.Properties; 6 | using ShadowSocks.Util; 7 | 8 | namespace ShadowSocks.Encryption 9 | { 10 | public static class MbedTLS 11 | { 12 | private const string DLLNAME = "libsscrypto.dll"; 13 | 14 | public const int MBEDTLS_ENCRYPT = 1; 15 | public const int MBEDTLS_DECRYPT = 0; 16 | 17 | static MbedTLS() 18 | { 19 | string dllPath = Utils.GetTempPath(DLLNAME); 20 | try 21 | { 22 | FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); 23 | } 24 | catch (IOException) 25 | { 26 | } 27 | catch (System.Exception e) 28 | { 29 | Logging.LogUsefulException(e); 30 | } 31 | LoadLibrary(dllPath); 32 | } 33 | 34 | public static byte[] MD5(byte[] input) 35 | { 36 | byte[] output = new byte[16]; 37 | md5(input, (uint) input.Length, output); 38 | return output; 39 | } 40 | 41 | [DllImport("Kernel32.dll")] 42 | private static extern IntPtr LoadLibrary(string path); 43 | 44 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 45 | public static extern void md5(byte[] input, uint ilen, byte[] output); 46 | 47 | /// 48 | /// Get cipher ctx size for unmanaged memory allocation 49 | /// 50 | /// 51 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 52 | public static extern int cipher_get_size_ex(); 53 | 54 | #region Cipher layer wrappers 55 | 56 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 57 | public static extern IntPtr cipher_info_from_string(string cipher_name); 58 | 59 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 60 | public static extern void cipher_init(IntPtr ctx); 61 | 62 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 63 | public static extern int cipher_setup(IntPtr ctx, IntPtr cipher_info); 64 | 65 | // XXX: Check operation before using it 66 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 67 | public static extern int cipher_setkey(IntPtr ctx, byte[] key, int key_bitlen, int operation); 68 | 69 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 70 | public static extern int cipher_set_iv(IntPtr ctx, byte[] iv, int iv_len); 71 | 72 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 73 | public static extern int cipher_reset(IntPtr ctx); 74 | 75 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 76 | public static extern int cipher_update(IntPtr ctx, byte[] input, int ilen, byte[] output, ref int olen); 77 | 78 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 79 | public static extern void cipher_free(IntPtr ctx); 80 | 81 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 82 | public static extern int cipher_auth_encrypt(IntPtr ctx, 83 | byte[] iv, uint iv_len, 84 | IntPtr ad, uint ad_len, 85 | byte[] input, uint ilen, 86 | byte[] output, ref uint olen, 87 | byte[] tag, uint tag_len); 88 | 89 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 90 | public static extern int cipher_auth_decrypt(IntPtr ctx, 91 | byte[] iv, uint iv_len, 92 | IntPtr ad, uint ad_len, 93 | byte[] input, uint ilen, 94 | byte[] output, ref uint olen, 95 | byte[] tag, uint tag_len); 96 | 97 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 98 | public static extern int hkdf(byte[] salt, 99 | int salt_len, byte[] ikm, int ikm_len, 100 | byte[] info, int info_len, byte[] okm, 101 | int okm_len); 102 | 103 | #endregion 104 | } 105 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/RNG.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | 4 | namespace ShadowSocks.Encryption 5 | { 6 | public static class RNG 7 | { 8 | private static RNGCryptoServiceProvider _rng = null; 9 | 10 | public static void Init() 11 | { 12 | if (_rng == null) 13 | _rng = new RNGCryptoServiceProvider(); 14 | } 15 | 16 | public static void Close() 17 | { 18 | if (_rng == null) return; 19 | _rng.Dispose(); 20 | _rng = null; 21 | } 22 | 23 | public static void Reload() 24 | { 25 | Close(); 26 | Init(); 27 | } 28 | 29 | public static void GetBytes(byte[] buf) 30 | { 31 | GetBytes(buf, buf.Length); 32 | } 33 | 34 | public static void GetBytes(byte[] buf, int len) 35 | { 36 | if (_rng == null) Reload(); 37 | try 38 | { 39 | _rng.GetBytes(buf, 0, len); 40 | } 41 | catch (System.Exception) 42 | { 43 | // the backup way 44 | byte[] tmp = new byte[len]; 45 | _rng.GetBytes(tmp); 46 | Buffer.BlockCopy(tmp, 0, buf, 0, len); 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/Sodium.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.InteropServices; 4 | using ShadowSocks.Controller; 5 | using ShadowSocks.Properties; 6 | using ShadowSocks.Util; 7 | 8 | namespace ShadowSocks.Encryption 9 | { 10 | public static class Sodium 11 | { 12 | private const string DLLNAME = "libsscrypto.dll"; 13 | 14 | private static bool _initialized = false; 15 | private static readonly object _initLock = new object(); 16 | 17 | public static bool AES256GCMAvailable { get; private set; } = false; 18 | 19 | static Sodium() 20 | { 21 | string dllPath = Utils.GetTempPath(DLLNAME); 22 | try 23 | { 24 | FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); 25 | } 26 | catch (IOException) 27 | { 28 | } 29 | catch (System.Exception e) 30 | { 31 | Logging.LogUsefulException(e); 32 | } 33 | LoadLibrary(dllPath); 34 | 35 | lock (_initLock) 36 | { 37 | if (!_initialized) 38 | { 39 | if (sodium_init() == -1) 40 | { 41 | throw new System.Exception("Failed to initialize sodium"); 42 | } 43 | else /* 1 means already initialized; 0 means success */ 44 | { 45 | _initialized = true; 46 | } 47 | 48 | AES256GCMAvailable = crypto_aead_aes256gcm_is_available() == 1; 49 | Logging.Debug($"sodium: AES256GCMAvailable is {AES256GCMAvailable}"); 50 | } 51 | } 52 | } 53 | 54 | [DllImport("Kernel32.dll")] 55 | private static extern IntPtr LoadLibrary(string path); 56 | 57 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 58 | private static extern int sodium_init(); 59 | 60 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 61 | private static extern int crypto_aead_aes256gcm_is_available(); 62 | 63 | #region AEAD 64 | 65 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 66 | public static extern int sodium_increment(byte[] n, int nlen); 67 | 68 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 69 | public static extern int crypto_aead_chacha20poly1305_ietf_encrypt(byte[] c, ref ulong clen_p, byte[] m, 70 | ulong mlen, byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k); 71 | 72 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 73 | public static extern int crypto_aead_chacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p, 74 | byte[] nsec, byte[] c, ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k); 75 | 76 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 77 | public static extern int crypto_aead_aes256gcm_encrypt(byte[] c, ref ulong clen_p, byte[] m, ulong mlen, 78 | byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k); 79 | 80 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 81 | public static extern int crypto_aead_aes256gcm_decrypt(byte[] m, ref ulong mlen_p, byte[] nsec, byte[] c, 82 | ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k); 83 | 84 | #endregion 85 | 86 | #region Stream 87 | 88 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 89 | public static extern int crypto_stream_salsa20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, 90 | byte[] k); 91 | 92 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 93 | public static extern int crypto_stream_chacha20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, 94 | byte[] k); 95 | 96 | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] 97 | public static extern int crypto_stream_chacha20_ietf_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, uint ic, 98 | byte[] k); 99 | 100 | #endregion 101 | } 102 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/Stream/StreamMbedTLSEncryptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using ShadowSocks.Encryption.Exception; 5 | 6 | namespace ShadowSocks.Encryption.Stream 7 | { 8 | public class StreamMbedTLSEncryptor 9 | : StreamEncryptor, IDisposable 10 | { 11 | const int CIPHER_RC4 = 1; 12 | const int CIPHER_AES = 2; 13 | const int CIPHER_BLOWFISH = 3; 14 | const int CIPHER_CAMELLIA = 4; 15 | 16 | private IntPtr _encryptCtx = IntPtr.Zero; 17 | private IntPtr _decryptCtx = IntPtr.Zero; 18 | 19 | public StreamMbedTLSEncryptor(string method, string password) 20 | : base(method, password) 21 | { 22 | } 23 | 24 | private static Dictionary _ciphers = new Dictionary { 25 | { "aes-128-cfb", new EncryptorInfo("AES-128-CFB128", 16, 16, CIPHER_AES) }, 26 | { "aes-192-cfb", new EncryptorInfo("AES-192-CFB128", 24, 16, CIPHER_AES) }, 27 | { "aes-256-cfb", new EncryptorInfo("AES-256-CFB128", 32, 16, CIPHER_AES) }, 28 | { "aes-128-ctr", new EncryptorInfo("AES-128-CTR", 16, 16, CIPHER_AES) }, 29 | { "aes-192-ctr", new EncryptorInfo("AES-192-CTR", 24, 16, CIPHER_AES) }, 30 | { "aes-256-ctr", new EncryptorInfo("AES-256-CTR", 32, 16, CIPHER_AES) }, 31 | { "bf-cfb", new EncryptorInfo("BLOWFISH-CFB64", 16, 8, CIPHER_BLOWFISH) }, 32 | { "camellia-128-cfb", new EncryptorInfo("CAMELLIA-128-CFB128", 16, 16, CIPHER_CAMELLIA) }, 33 | { "camellia-192-cfb", new EncryptorInfo("CAMELLIA-192-CFB128", 24, 16, CIPHER_CAMELLIA) }, 34 | { "camellia-256-cfb", new EncryptorInfo("CAMELLIA-256-CFB128", 32, 16, CIPHER_CAMELLIA) }, 35 | { "rc4-md5", new EncryptorInfo("ARC4-128", 16, 16, CIPHER_RC4) } 36 | }; 37 | 38 | public static List SupportedCiphers() 39 | { 40 | return new List(_ciphers.Keys); 41 | } 42 | 43 | protected override Dictionary getCiphers() 44 | { 45 | return _ciphers; 46 | } 47 | 48 | protected override void initCipher(byte[] iv, bool isEncrypt) 49 | { 50 | base.initCipher(iv, isEncrypt); 51 | IntPtr ctx = Marshal.AllocHGlobal(MbedTLS.cipher_get_size_ex()); 52 | if (isEncrypt) 53 | { 54 | _encryptCtx = ctx; 55 | } 56 | else 57 | { 58 | _decryptCtx = ctx; 59 | } 60 | byte[] realkey; 61 | if (_method == "rc4-md5") 62 | { 63 | byte[] temp = new byte[keyLen + ivLen]; 64 | realkey = new byte[keyLen]; 65 | Array.Copy(_key, 0, temp, 0, keyLen); 66 | Array.Copy(iv, 0, temp, keyLen, ivLen); 67 | realkey = MbedTLS.MD5(temp); 68 | } 69 | else 70 | { 71 | realkey = _key; 72 | } 73 | MbedTLS.cipher_init(ctx); 74 | if (MbedTLS.cipher_setup( ctx, MbedTLS.cipher_info_from_string( _innerLibName ) ) != 0 ) 75 | throw new System.Exception("Cannot initialize mbed TLS cipher context"); 76 | /* 77 | * MbedTLS takes key length by bit 78 | * cipher_setkey() will set the correct key schedule 79 | * and operation 80 | * 81 | * MBEDTLS_AES_{EN,DE}CRYPT 82 | * == MBEDTLS_BLOWFISH_{EN,DE}CRYPT 83 | * == MBEDTLS_CAMELLIA_{EN,DE}CRYPT 84 | * == MBEDTLS_{EN,DE}CRYPT 85 | * 86 | */ 87 | if (MbedTLS.cipher_setkey(ctx, realkey, keyLen * 8, 88 | isEncrypt ? MbedTLS.MBEDTLS_ENCRYPT : MbedTLS.MBEDTLS_DECRYPT) != 0 ) 89 | throw new System.Exception("Cannot set mbed TLS cipher key"); 90 | if (MbedTLS.cipher_set_iv(ctx, iv, ivLen) != 0) 91 | throw new System.Exception("Cannot set mbed TLS cipher IV"); 92 | if (MbedTLS.cipher_reset(ctx) != 0) 93 | throw new System.Exception("Cannot finalize mbed TLS cipher context"); 94 | } 95 | 96 | protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) 97 | { 98 | // C# could be multi-threaded 99 | if (_disposed) 100 | { 101 | throw new ObjectDisposedException(this.ToString()); 102 | } 103 | if (MbedTLS.cipher_update(isEncrypt ? _encryptCtx : _decryptCtx, 104 | buf, length, outbuf, ref length) != 0 ) 105 | throw new CryptoErrorException(); 106 | } 107 | 108 | #region IDisposable 109 | 110 | private bool _disposed; 111 | 112 | // instance based lock 113 | private readonly object _lock = new object(); 114 | 115 | public override void Dispose() 116 | { 117 | Dispose(true); 118 | GC.SuppressFinalize(this); 119 | } 120 | 121 | ~StreamMbedTLSEncryptor() 122 | { 123 | Dispose(false); 124 | } 125 | 126 | protected virtual void Dispose(bool disposing) 127 | { 128 | lock (_lock) 129 | { 130 | if (_disposed) return; 131 | _disposed = true; 132 | } 133 | 134 | if (disposing) 135 | { 136 | // free managed objects 137 | } 138 | 139 | // free unmanaged objects 140 | if (_encryptCtx != IntPtr.Zero) 141 | { 142 | MbedTLS.cipher_free(_encryptCtx); 143 | Marshal.FreeHGlobal(_encryptCtx); 144 | _encryptCtx = IntPtr.Zero; 145 | } 146 | if (_decryptCtx != IntPtr.Zero) 147 | { 148 | MbedTLS.cipher_free(_decryptCtx); 149 | Marshal.FreeHGlobal(_decryptCtx); 150 | _decryptCtx = IntPtr.Zero; 151 | } 152 | } 153 | 154 | #endregion 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using ShadowSocks.Encryption.Exception; 4 | 5 | namespace ShadowSocks.Encryption.Stream 6 | { 7 | public class StreamSodiumEncryptor 8 | : StreamEncryptor, IDisposable 9 | { 10 | const int CIPHER_SALSA20 = 1; 11 | const int CIPHER_CHACHA20 = 2; 12 | const int CIPHER_CHACHA20_IETF = 3; 13 | 14 | const int SODIUM_BLOCK_SIZE = 64; 15 | 16 | protected int _encryptBytesRemaining; 17 | protected int _decryptBytesRemaining; 18 | protected ulong _encryptIC; 19 | protected ulong _decryptIC; 20 | protected byte[] _encryptBuf; 21 | protected byte[] _decryptBuf; 22 | 23 | public StreamSodiumEncryptor(string method, string password) 24 | : base(method, password) 25 | { 26 | _encryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; 27 | _decryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; 28 | } 29 | 30 | private static Dictionary _ciphers = new Dictionary { 31 | { "salsa20", new EncryptorInfo(32, 8, CIPHER_SALSA20) }, 32 | { "chacha20", new EncryptorInfo(32, 8, CIPHER_CHACHA20) }, 33 | { "chacha20-ietf", new EncryptorInfo(32, 12, CIPHER_CHACHA20_IETF) } 34 | }; 35 | 36 | protected override Dictionary getCiphers() 37 | { 38 | return _ciphers; 39 | } 40 | 41 | public static List SupportedCiphers() 42 | { 43 | return new List(_ciphers.Keys); 44 | } 45 | 46 | protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) 47 | { 48 | // TODO write a unidirection cipher so we don't have to if if if 49 | int bytesRemaining; 50 | ulong ic; 51 | byte[] sodiumBuf; 52 | byte[] iv; 53 | int ret = -1; 54 | 55 | if (isEncrypt) 56 | { 57 | bytesRemaining = _encryptBytesRemaining; 58 | ic = _encryptIC; 59 | sodiumBuf = _encryptBuf; 60 | iv = _encryptIV; 61 | } 62 | else 63 | { 64 | bytesRemaining = _decryptBytesRemaining; 65 | ic = _decryptIC; 66 | sodiumBuf = _decryptBuf; 67 | iv = _decryptIV; 68 | } 69 | int padding = bytesRemaining; 70 | Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length); 71 | 72 | switch (_cipher) 73 | { 74 | case CIPHER_SALSA20: 75 | ret = Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); 76 | break; 77 | case CIPHER_CHACHA20: 78 | ret = Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); 79 | break; 80 | case CIPHER_CHACHA20_IETF: 81 | ret = Sodium.crypto_stream_chacha20_ietf_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, (uint)ic, _key); 82 | break; 83 | } 84 | if (ret != 0) throw new CryptoErrorException(); 85 | 86 | Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length); 87 | padding += length; 88 | ic += (ulong)padding / SODIUM_BLOCK_SIZE; 89 | bytesRemaining = padding % SODIUM_BLOCK_SIZE; 90 | 91 | if (isEncrypt) 92 | { 93 | _encryptBytesRemaining = bytesRemaining; 94 | _encryptIC = ic; 95 | } 96 | else 97 | { 98 | _decryptBytesRemaining = bytesRemaining; 99 | _decryptIC = ic; 100 | } 101 | } 102 | 103 | public override void Dispose() 104 | { 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Exceptions/AlleyException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ShadowSocks.Exceptions 8 | { 9 | class GreenDotException: Exception 10 | { 11 | public GreenDotException(string message) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Extensions/JsonExtensions.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ShadowSocks.Extensions 10 | { 11 | public static class JsonExtensions 12 | { 13 | public static bool ok(this JToken token) 14 | { 15 | if (token == null) { 16 | return false; 17 | } 18 | 19 | var status = token["code"]; 20 | return status!=null && status.Type == JTokenType.Integer && status.ToString().Equals("200"); 21 | } 22 | 23 | public static bool expired(this JToken token) { 24 | if (token == null) 25 | { 26 | return false; 27 | } 28 | 29 | var status = token["code"]; 30 | return status != null && status.Type == JTokenType.Integer && status.ToString().Equals("403"); 31 | } 32 | 33 | public static dynamic content(this JToken token) { 34 | return token["content"]; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ShadowSocks.Extensions 8 | { 9 | public static class StringExtensions 10 | { 11 | public static string ToBase64(this string value) 12 | { 13 | var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(value); 14 | return System.Convert.ToBase64String(plainTextBytes); 15 | } 16 | public static string FromBase64(this string value) 17 | { 18 | var base64EncodedBytes = System.Convert.FromBase64String(value); 19 | return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); 20 | } 21 | public static string ToUrlEncodeBase64(this string value) 22 | { 23 | return Uri.EscapeDataString(value.ToBase64()); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /shadowsocks-csharp/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Model/HotKeyConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ShadowSocks.Model 4 | { 5 | /* 6 | * Format: 7 | * + 8 | * 9 | */ 10 | 11 | [Serializable] 12 | public class HotkeyConfig 13 | { 14 | public string SwitchSystemProxy; 15 | public string SwitchSystemProxyMode; 16 | public string SwitchAllowLan; 17 | public string ShowLogs; 18 | public string ServerMoveUp; 19 | public string ServerMoveDown; 20 | 21 | public HotkeyConfig() 22 | { 23 | SwitchSystemProxy = ""; 24 | SwitchSystemProxyMode = ""; 25 | SwitchAllowLan = ""; 26 | ShowLogs = ""; 27 | ServerMoveUp = ""; 28 | ServerMoveDown = ""; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Model/LogViewerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | using Newtonsoft.Json; 5 | 6 | namespace ShadowSocks.Model 7 | { 8 | [Serializable] 9 | public class LogViewerConfig 10 | { 11 | public bool topMost; 12 | public bool wrapText; 13 | public bool toolbarShown; 14 | 15 | public Font Font { get; set; } = new Font("Consolas", 8F); 16 | 17 | public Color BackgroundColor { get; set; } = Color.Black; 18 | 19 | public Color TextColor { get; set; } = Color.White; 20 | 21 | public LogViewerConfig() 22 | { 23 | topMost = false; 24 | wrapText = false; 25 | toolbarShown = false; 26 | } 27 | 28 | 29 | #region Size 30 | 31 | public void SaveSize() 32 | { 33 | Properties.Settings.Default.Save(); 34 | } 35 | 36 | [JsonIgnore] 37 | public int Width 38 | { 39 | get { return Properties.Settings.Default.LogViewerWidth; } 40 | set { Properties.Settings.Default.LogViewerWidth = value; } 41 | } 42 | 43 | [JsonIgnore] 44 | public int Height 45 | { 46 | get { return Properties.Settings.Default.LogViewerHeight; } 47 | set { Properties.Settings.Default.LogViewerHeight = value; } 48 | } 49 | [JsonIgnore] 50 | public int Top 51 | { 52 | get { return Properties.Settings.Default.LogViewerTop; } 53 | set { Properties.Settings.Default.LogViewerTop = value; } 54 | } 55 | [JsonIgnore] 56 | public int Left 57 | { 58 | get { return Properties.Settings.Default.LogViewerLeft; } 59 | set { Properties.Settings.Default.LogViewerLeft = value; } 60 | } 61 | [JsonIgnore] 62 | public bool Maximized 63 | { 64 | get { return Properties.Settings.Default.LogViewerMaximized; } 65 | set { Properties.Settings.Default.LogViewerMaximized = value; } 66 | } 67 | 68 | [JsonIgnore] 69 | // Use GetBestTop() and GetBestLeft() to ensure the log viwer form can be always display IN screen. 70 | public int BestLeft 71 | { 72 | get 73 | { 74 | int width = Width; 75 | width = (width >= 400) ? width : 400; // set up the minimum size 76 | return Screen.PrimaryScreen.WorkingArea.Width - width; 77 | } 78 | } 79 | 80 | [JsonIgnore] 81 | public int BestTop 82 | { 83 | get 84 | { 85 | int height = Height; 86 | height = (height >= 200) ? height : 200; // set up the minimum size 87 | return Screen.PrimaryScreen.WorkingArea.Height - height; 88 | } 89 | } 90 | 91 | #endregion 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Model/ProxyConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ShadowSocks.Model 4 | { 5 | [Serializable] 6 | public class ProxyConfig 7 | { 8 | public const int PROXY_SOCKS5 = 0; 9 | public const int PROXY_HTTP = 1; 10 | 11 | public const int MaxProxyTimeoutSec = 10; 12 | private const int DefaultProxyTimeoutSec = 3; 13 | 14 | public bool useProxy; 15 | public int proxyType; 16 | public string proxyServer; 17 | public int proxyPort; 18 | public int proxyTimeout; 19 | 20 | public ProxyConfig() 21 | { 22 | useProxy = false; 23 | proxyType = PROXY_SOCKS5; 24 | proxyServer = ""; 25 | proxyPort = 0; 26 | proxyTimeout = DefaultProxyTimeoutSec; 27 | } 28 | 29 | public void CheckConfig() 30 | { 31 | if (proxyType < PROXY_SOCKS5 || proxyType > PROXY_HTTP) 32 | { 33 | proxyType = PROXY_SOCKS5; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Model/ServerNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ShadowSocks.Model 8 | { 9 | public class ServerNode 10 | { 11 | private int id; 12 | private string name; 13 | private string icon; 14 | private string remark; 15 | private int linkcount; 16 | private bool selected; 17 | private string host; 18 | private string port; 19 | private string method; 20 | private string password; 21 | 22 | public int Linkcount { get => linkcount; set => linkcount = value; } 23 | public string Remark { get => remark; set => remark = value; } 24 | public string Icon { get => icon; set => icon = value; } 25 | public string Name { get => name; set => name = value; } 26 | public bool Selected { get => selected; set => selected = value; } 27 | public string Host { get => host; set => host = value; } 28 | public string Port { get => port; set => port = value; } 29 | public string Method { get => method; set => method = value; } 30 | public string Password { get => password; set => password = value; } 31 | public int Id { get => id; set => id = value; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Model/SiteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ShadowSocks.Model 8 | { 9 | public class SiteConfig 10 | { 11 | private Properties.Settings settings = Properties.Settings.Default; 12 | 13 | public int usergiftday 14 | { 15 | get 16 | { 17 | return settings.usergiftday; 18 | } 19 | set 20 | { 21 | settings.usergiftday = value; 22 | settings.Save(); 23 | } 24 | } 25 | 26 | public string sitename 27 | { 28 | get 29 | { 30 | return settings.sitename; 31 | } 32 | set 33 | { 34 | settings.sitename = value; 35 | settings.Save(); 36 | } 37 | } 38 | 39 | public string siteword 40 | { 41 | get 42 | { 43 | return settings.siteword; 44 | } 45 | set 46 | { 47 | settings.siteword = value; 48 | settings.Save(); 49 | } 50 | } 51 | 52 | public string company 53 | { 54 | get 55 | { 56 | return settings.company; 57 | } 58 | set 59 | { 60 | settings.company = value; 61 | settings.Save(); 62 | } 63 | } 64 | 65 | public string version 66 | { 67 | get 68 | { 69 | return settings.version; 70 | } 71 | set 72 | { 73 | settings.version = value; 74 | settings.Save(); 75 | } 76 | } 77 | 78 | public void setConfig(dynamic configInfo) 79 | { 80 | if (configInfo["usergiftday"]!=null) 81 | { 82 | this.usergiftday = Convert.ToInt32(configInfo["usergiftday"]); 83 | } 84 | 85 | this.sitename = (string)configInfo["sitename"]; 86 | this.siteword = (string)configInfo["siteword"]; 87 | this.company = (string)configInfo["company"]; 88 | } 89 | 90 | private static SiteConfig _config = null; 91 | 92 | public static SiteConfig instance() 93 | { 94 | if (_config == null) 95 | { 96 | _config = new SiteConfig(); 97 | } 98 | return _config; 99 | } 100 | 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Model/StatisticsRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace ShadowSocks.Model 7 | { 8 | // Simple processed records for a short period of time 9 | public class StatisticsRecord 10 | { 11 | public DateTime Timestamp { get; set; } = DateTime.Now; 12 | public string ServerIdentifier { get; set; } 13 | 14 | // in ping-only records, these fields would be null 15 | public int? AverageLatency; 16 | public int? MinLatency; 17 | public int? MaxLatency; 18 | 19 | private bool EmptyLatencyData => (AverageLatency == null) && (MinLatency == null) && (MaxLatency == null); 20 | 21 | public int? AverageInboundSpeed; 22 | public int? MinInboundSpeed; 23 | public int? MaxInboundSpeed; 24 | 25 | private bool EmptyInboundSpeedData 26 | => (AverageInboundSpeed == null) && (MinInboundSpeed == null) && (MaxInboundSpeed == null); 27 | 28 | public int? AverageOutboundSpeed; 29 | public int? MinOutboundSpeed; 30 | public int? MaxOutboundSpeed; 31 | 32 | private bool EmptyOutboundSpeedData 33 | => (AverageOutboundSpeed == null) && (MinOutboundSpeed == null) && (MaxOutboundSpeed == null); 34 | 35 | // if user disabled ping test, response would be null 36 | public int? AverageResponse; 37 | public int? MinResponse; 38 | public int? MaxResponse; 39 | public float? PackageLoss; 40 | 41 | private bool EmptyResponseData 42 | => (AverageResponse == null) && (MinResponse == null) && (MaxResponse == null) && (PackageLoss == null); 43 | 44 | public bool IsEmptyData() { 45 | return EmptyInboundSpeedData && EmptyOutboundSpeedData && EmptyResponseData && EmptyLatencyData; 46 | } 47 | 48 | public StatisticsRecord() 49 | { 50 | } 51 | 52 | public StatisticsRecord(string identifier, ICollection inboundSpeedRecords, ICollection outboundSpeedRecords, ICollection latencyRecords) 53 | { 54 | ServerIdentifier = identifier; 55 | var inbound = inboundSpeedRecords?.Where(s => s > 0).ToList(); 56 | if (inbound != null && inbound.Any()) 57 | { 58 | AverageInboundSpeed = (int) inbound.Average(); 59 | MinInboundSpeed = inbound.Min(); 60 | MaxInboundSpeed = inbound.Max(); 61 | } 62 | var outbound = outboundSpeedRecords?.Where(s => s > 0).ToList(); 63 | if (outbound!= null && outbound.Any()) 64 | { 65 | AverageOutboundSpeed = (int) outbound.Average(); 66 | MinOutboundSpeed = outbound.Min(); 67 | MaxOutboundSpeed = outbound.Max(); 68 | } 69 | var latency = latencyRecords?.Where(s => s > 0).ToList(); 70 | if (latency!= null && latency.Any()) 71 | { 72 | AverageLatency = (int) latency.Average(); 73 | MinLatency = latency.Min(); 74 | MaxLatency = latency.Max(); 75 | } 76 | } 77 | 78 | public StatisticsRecord(string identifier, ICollection responseRecords) 79 | { 80 | ServerIdentifier = identifier; 81 | SetResponse(responseRecords); 82 | } 83 | 84 | public void SetResponse(ICollection responseRecords) 85 | { 86 | if (responseRecords == null) return; 87 | var records = responseRecords.Where(response => response != null).Select(response => response.Value).ToList(); 88 | if (!records.Any()) return; 89 | AverageResponse = (int?) records.Average(); 90 | MinResponse = records.Min(); 91 | MaxResponse = records.Max(); 92 | PackageLoss = responseRecords.Count(response => response != null)/(float) responseRecords.Count; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Model/StatisticsStrategyConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | using Newtonsoft.Json; 8 | 9 | using ShadowSocks.Controller; 10 | 11 | namespace ShadowSocks.Model 12 | { 13 | [Serializable] 14 | public class StatisticsStrategyConfiguration 15 | { 16 | public static readonly string ID = "com.shadowsocks.strategy.statistics"; 17 | public bool StatisticsEnabled { get; set; } = false; 18 | public bool ByHourOfDay { get; set; } = true; 19 | public bool Ping { get; set; } 20 | public int ChoiceKeptMinutes { get; set; } = 10; 21 | public int DataCollectionMinutes { get; set; } = 10; 22 | public int RepeatTimesNum { get; set; } = 4; 23 | 24 | private const string ConfigFile = "statistics-config.json"; 25 | 26 | public static StatisticsStrategyConfiguration Load() 27 | { 28 | try 29 | { 30 | var content = File.ReadAllText(ConfigFile); 31 | var configuration = JsonConvert.DeserializeObject(content); 32 | return configuration; 33 | } 34 | catch (FileNotFoundException) 35 | { 36 | var configuration = new StatisticsStrategyConfiguration(); 37 | Save(configuration); 38 | return configuration; 39 | } 40 | catch (Exception e) 41 | { 42 | Logging.LogUsefulException(e); 43 | return new StatisticsStrategyConfiguration(); 44 | } 45 | } 46 | 47 | public static void Save(StatisticsStrategyConfiguration configuration) 48 | { 49 | try 50 | { 51 | var content = JsonConvert.SerializeObject(configuration, Formatting.Indented); 52 | File.WriteAllText(ConfigFile, content); 53 | } 54 | catch (Exception e) 55 | { 56 | Logging.LogUsefulException(e); 57 | } 58 | } 59 | 60 | public Dictionary Calculations; 61 | 62 | public StatisticsStrategyConfiguration() 63 | { 64 | var properties = typeof(StatisticsRecord).GetFields(BindingFlags.Instance | BindingFlags.Public); 65 | Calculations = properties.ToDictionary(p => p.Name, _ => (float)0); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Model/SysproxyConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ShadowSocks.Model 4 | { 5 | /* 6 | * Data come from WinINET 7 | */ 8 | 9 | [Serializable] 10 | public class SysproxyConfig 11 | { 12 | public bool UserSettingsRecorded; 13 | public string Flags; 14 | public string ProxyServer; 15 | public string BypassList; 16 | public string PacUrl; 17 | 18 | public SysproxyConfig() 19 | { 20 | UserSettingsRecorded = false; 21 | Flags = "1"; 22 | ProxyServer = ""; 23 | BypassList = ""; 24 | PacUrl = ""; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Threading; 5 | using System.Windows.Forms; 6 | using Microsoft.Win32; 7 | 8 | using ShadowSocks.Controller; 9 | using ShadowSocks.Controller.Hotkeys; 10 | using ShadowSocks.Util; 11 | using ShadowSocks.View; 12 | 13 | namespace ShadowSocks 14 | { 15 | static class Program 16 | { 17 | /// 18 | /// 应用程序的主入口点。 19 | /// 20 | [STAThread] 21 | static void Main() 22 | { 23 | if (!Utils.IsWinVistaOrHigher()) 24 | { 25 | MessageBox.Show( 26 | "不支持的操作系统版本,最低需求为Windows Vista。", 27 | "系统提示", 28 | MessageBoxButtons.OK, 29 | MessageBoxIcon.Error 30 | ); 31 | return; 32 | } 33 | 34 | if (!Utils.IsSupportedRuntimeVersion()) 35 | { 36 | MessageBox.Show( 37 | "当前 .NET Framework 版本过低,请升级至4.6.2或更新版本。", 38 | "系统提示", 39 | MessageBoxButtons.OK, 40 | MessageBoxIcon.Error 41 | ); 42 | 43 | Process.Start("http://dotnetsocial.cloudapp.net/GetDotnet?tfm=.NETFramework,Version=v4.6.2"); 44 | return; 45 | } 46 | 47 | Utils.ReleaseMemory(true); 48 | 49 | using (Mutex mutex = new Mutex(false, $"Global\\GreenDot_{Application.StartupPath.GetHashCode()}")) 50 | { 51 | Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 52 | Application.ThreadException += Application_ThreadException; 53 | AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 54 | Application.ApplicationExit += Application_ApplicationExit; 55 | SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; 56 | Application.EnableVisualStyles(); 57 | Application.SetCompatibleTextRenderingDefault(false); 58 | 59 | if (!mutex.WaitOne(0, false)) 60 | { 61 | Process[] oldProcesses = Process.GetProcessesByName("GreenDot Windows"); 62 | if (oldProcesses.Length > 0) 63 | { 64 | Process oldProcess = oldProcesses[0]; 65 | } 66 | MessageBox.Show( 67 | "加速服务正在运行中,请在任务栏查找相关图标。", 68 | "系统提示", 69 | MessageBoxButtons.OK, 70 | MessageBoxIcon.Information 71 | ); 72 | return; 73 | } 74 | 75 | Directory.SetCurrentDirectory(Application.StartupPath); 76 | 77 | Logging.OpenLogFile(); 78 | 79 | HotKeys.Init(ViewManager.instance.MainController); 80 | 81 | Login loginForm = new Login(); 82 | Application.Run(loginForm); 83 | } 84 | } 85 | 86 | private static int exited = 0; 87 | 88 | private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 89 | { 90 | if (Interlocked.Increment(ref exited) == 1) 91 | { 92 | Environment.Exit(0); 93 | } 94 | } 95 | 96 | private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) 97 | { 98 | if (Interlocked.Increment(ref exited) == 1) 99 | { 100 | Environment.Exit(0); 101 | } 102 | } 103 | 104 | private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) 105 | { 106 | ShadowSocksController mainController = ViewManager.instance.MainController; 107 | 108 | switch (e.Mode) 109 | { 110 | case PowerModes.Resume: 111 | Logging.Info("os wake up"); 112 | if (mainController != null) 113 | { 114 | System.Timers.Timer timer = new System.Timers.Timer(10 * 1000); 115 | timer.Elapsed += Timer_Elapsed; 116 | timer.AutoReset = false; 117 | timer.Enabled = true; 118 | timer.Start(); 119 | } 120 | break; 121 | case PowerModes.Suspend: 122 | if (mainController != null) 123 | { 124 | mainController.Stop(); 125 | Logging.Info("main controller stopped"); 126 | } 127 | Logging.Info("os suspend"); 128 | break; 129 | } 130 | } 131 | 132 | private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 133 | { 134 | try 135 | { 136 | if (ViewManager.instance.MainController != null) 137 | { 138 | ViewManager.instance.MainController.Start(); 139 | Logging.Info("main controller started"); 140 | } 141 | } 142 | catch (Exception ex) 143 | { 144 | Logging.LogUsefulException(ex); 145 | } 146 | finally 147 | { 148 | try 149 | { 150 | System.Timers.Timer timer = (System.Timers.Timer)sender; 151 | timer.Enabled = false; 152 | timer.Stop(); 153 | timer.Dispose(); 154 | } 155 | catch (Exception ex) 156 | { 157 | Logging.LogUsefulException(ex); 158 | } 159 | } 160 | } 161 | 162 | private static void Application_ApplicationExit(object sender, EventArgs e) 163 | { 164 | Application.ApplicationExit -= Application_ApplicationExit; 165 | SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; 166 | Application.ThreadException -= Application_ThreadException; 167 | HotKeys.Destroy(); 168 | 169 | ViewManager viewManager = ViewManager.instance; 170 | 171 | if (viewManager.MainController != null) 172 | { 173 | viewManager.closeMainController(); 174 | } 175 | SystemProxy.Disable(); 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // 有关程序集的一般信息由以下 5 | // 控制。更改这些特性值可修改 6 | // 与程序集关联的信息。 7 | [assembly: AssemblyTitle("GreenDot Windows")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("GreenDot")] 11 | [assembly: AssemblyProduct("GreenDot Windows")] 12 | [assembly: AssemblyCopyright("Copyright © 2017")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // 将 ComVisible 设置为 false 会使此程序集中的类型 17 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 18 | //请将此类型的 ComVisible 特性设置为 true。 19 | [assembly: ComVisible(false)] 20 | 21 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 22 | [assembly: Guid("84529da0-a4b4-4258-a1c6-26e093170c5c")] 23 | 24 | // 程序集的版本信息由下列四个值组成: 25 | // 26 | // 主版本 27 | // 次版本 28 | // 生成号 29 | // 修订号 30 | // 31 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 32 | // 方法是按如下所示使用“*”: : 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.2")] 35 | [assembly: AssemblyFileVersion("1.0.2")] 36 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Properties/DataSources/Shadowsocks.Model.StatisticsStrategyConfiguration.datasource: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | ShadowSocks.Model.StatisticsStrategyConfiguration, ShadowSocks, Version=2.5.2.0, Culture=neutral, PublicKeyToken=null 10 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 0 22 | 23 | 24 | 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 0 40 | 41 | 42 | 0 43 | 44 | 45 | 0 46 | 47 | 48 | 0 49 | 50 | 51 | False 52 | 53 | 54 | 0 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Proxy/DirectConnect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Sockets; 4 | using System.Threading; 5 | using ShadowSocks.Util.Sockets; 6 | 7 | namespace ShadowSocks.Proxy 8 | { 9 | public class DirectConnect : IProxy 10 | { 11 | private class FakeAsyncResult : IAsyncResult 12 | { 13 | public FakeAsyncResult(object state) 14 | { 15 | AsyncState = state; 16 | } 17 | 18 | public bool IsCompleted { get; } = true; 19 | public WaitHandle AsyncWaitHandle { get; } = null; 20 | public object AsyncState { get; } 21 | public bool CompletedSynchronously { get; } = true; 22 | } 23 | 24 | private class FakeEndPoint : EndPoint 25 | { 26 | public override AddressFamily AddressFamily { get; } = AddressFamily.Unspecified; 27 | 28 | public override string ToString() 29 | { 30 | return "null proxy"; 31 | } 32 | } 33 | 34 | private WrappedSocket _remote = new WrappedSocket(); 35 | 36 | public EndPoint LocalEndPoint => _remote.LocalEndPoint; 37 | 38 | public EndPoint ProxyEndPoint { get; } = new FakeEndPoint(); 39 | public EndPoint DestEndPoint { get; private set; } 40 | 41 | public void BeginConnectProxy(EndPoint remoteEP, AsyncCallback callback, object state) 42 | { 43 | // do nothing 44 | 45 | var r = new FakeAsyncResult(state); 46 | callback?.Invoke(r); 47 | } 48 | 49 | public void EndConnectProxy(IAsyncResult asyncResult) 50 | { 51 | // do nothing 52 | } 53 | 54 | public void BeginConnectDest(EndPoint destEndPoint, AsyncCallback callback, object state) 55 | { 56 | DestEndPoint = destEndPoint; 57 | 58 | _remote.BeginConnect(destEndPoint, callback, state); 59 | } 60 | 61 | public void EndConnectDest(IAsyncResult asyncResult) 62 | { 63 | _remote.EndConnect(asyncResult); 64 | _remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); 65 | } 66 | 67 | public void BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, 68 | object state) 69 | { 70 | _remote.BeginSend(buffer, offset, size, socketFlags, callback, state); 71 | } 72 | 73 | public int EndSend(IAsyncResult asyncResult) 74 | { 75 | return _remote.EndSend(asyncResult); 76 | } 77 | 78 | public void BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, 79 | object state) 80 | { 81 | _remote.BeginReceive(buffer, offset, size, socketFlags, callback, state); 82 | } 83 | 84 | public int EndReceive(IAsyncResult asyncResult) 85 | { 86 | return _remote.EndReceive(asyncResult); 87 | } 88 | 89 | public void Shutdown(SocketShutdown how) 90 | { 91 | _remote.Shutdown(how); 92 | } 93 | 94 | public void Close() 95 | { 96 | _remote.Dispose(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Proxy/IProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Sockets; 4 | 5 | namespace ShadowSocks.Proxy 6 | { 7 | 8 | public interface IProxy 9 | { 10 | EndPoint LocalEndPoint { get; } 11 | 12 | EndPoint ProxyEndPoint { get; } 13 | 14 | EndPoint DestEndPoint { get; } 15 | 16 | void BeginConnectProxy(EndPoint remoteEP, AsyncCallback callback, object state); 17 | 18 | void EndConnectProxy(IAsyncResult asyncResult); 19 | 20 | void BeginConnectDest(EndPoint destEndPoint, AsyncCallback callback, object state); 21 | 22 | void EndConnectDest(IAsyncResult asyncResult); 23 | 24 | void BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, 25 | object state); 26 | 27 | int EndSend(IAsyncResult asyncResult); 28 | 29 | void BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, 30 | object state); 31 | 32 | int EndReceive(IAsyncResult asyncResult); 33 | 34 | void Shutdown(SocketShutdown how); 35 | 36 | void Close(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-canada.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-canada.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-china.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-china.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-finland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-finland.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-france.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-france.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-germany.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-germany.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-hongkong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-hongkong.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-ireland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-ireland.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-italy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-italy.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-japan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-japan.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-korea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-korea.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-norway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-norway.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-russia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-russia.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-spain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-spain.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-taiwan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-taiwan.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-uk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-uk.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag-usa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag-usa.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/flag/flag_holland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/flag/flag_holland.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/ico-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/ico-check.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/ico-in24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/ico-in24.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/ico-out24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/ico-out24.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/ico-vip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/ico-vip.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/ico_connecting.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/ico_connecting.gif -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/ico_connection_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/ico_connection_stop.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/ico_loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/ico_loading.gif -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/logo-white.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/logo.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/logo32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/logo32.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/logo40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/logo40.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Resources/logo48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/Resources/logo48.png -------------------------------------------------------------------------------- /shadowsocks-csharp/Settings.cs: -------------------------------------------------------------------------------- 1 | namespace ShadowSocks.Properties { 2 | 3 | 4 | // 通过此类可以处理设置类的特定事件: 5 | // 在更改某个设置的值之前将引发 SettingChanging 事件。 6 | // 在更改某个设置的值之后将引发 PropertyChanged 事件。 7 | // 在加载设置值之后将引发 SettingsLoaded 事件。 8 | // 在保存设置值之前将引发 SettingsSaving 事件。 9 | internal sealed partial class Settings { 10 | 11 | public Settings() { 12 | // // 若要为保存和更改设置添加事件处理程序,请取消注释下列行: 13 | // 14 | // this.SettingChanging += this.SettingChangingEventHandler; 15 | // 16 | // this.SettingsSaving += this.SettingsSavingEventHandler; 17 | // 18 | } 19 | 20 | private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { 21 | // 在此处添加用于处理 SettingChangingEvent 事件的代码。 22 | } 23 | 24 | private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { 25 | // 在此处添加用于处理 SettingsSaving 事件的代码。 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/DateHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ShadowSocks.Util 8 | { 9 | public static class DateHelper 10 | { 11 | public static TimeSpan subtractCurrentDate(String dateStr) { 12 | String currentDateStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); 13 | DateTime currentDate = DateTime.Parse(currentDateStr); 14 | DateTime subtractDate = DateTime.Parse(dateStr); 15 | TimeSpan span = subtractDate.Subtract(currentDate); 16 | return span; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/ProcessManagement/Job.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using ShadowSocks.Controller; 5 | 6 | namespace ShadowSocks.Util.ProcessManagement 7 | { 8 | public class Job : IDisposable 9 | { 10 | private IntPtr handle = IntPtr.Zero; 11 | 12 | public Job() 13 | { 14 | handle = CreateJobObject(IntPtr.Zero, null); 15 | var extendedInfoPtr = IntPtr.Zero; 16 | var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION 17 | { 18 | LimitFlags = 0x2000 19 | }; 20 | 21 | var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION 22 | { 23 | BasicLimitInformation = info 24 | }; 25 | 26 | try 27 | { 28 | int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); 29 | extendedInfoPtr = Marshal.AllocHGlobal(length); 30 | Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); 31 | 32 | if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, 33 | (uint) length)) 34 | throw new Exception(string.Format("Unable to set information. Error: {0}", 35 | Marshal.GetLastWin32Error())); 36 | } 37 | finally 38 | { 39 | if (extendedInfoPtr != IntPtr.Zero) 40 | { 41 | Marshal.FreeHGlobal(extendedInfoPtr); 42 | extendedInfoPtr = IntPtr.Zero; 43 | } 44 | } 45 | } 46 | 47 | public bool AddProcess(IntPtr processHandle) 48 | { 49 | var succ = AssignProcessToJobObject(handle, processHandle); 50 | 51 | if (!succ) 52 | { 53 | Logging.Error("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error()); 54 | } 55 | 56 | return succ; 57 | } 58 | 59 | public bool AddProcess(int processId) 60 | { 61 | return AddProcess(Process.GetProcessById(processId).Handle); 62 | } 63 | 64 | #region IDisposable 65 | 66 | private bool disposed; 67 | 68 | public void Dispose() 69 | { 70 | Dispose(true); 71 | GC.SuppressFinalize(this); 72 | } 73 | 74 | protected virtual void Dispose(bool disposing) 75 | { 76 | if (disposed) return; 77 | disposed = true; 78 | 79 | if (disposing) 80 | { 81 | // no managed objects to free 82 | } 83 | 84 | if (handle != IntPtr.Zero) 85 | { 86 | CloseHandle(handle); 87 | handle = IntPtr.Zero; 88 | } 89 | } 90 | 91 | ~Job() 92 | { 93 | Dispose(false); 94 | } 95 | 96 | #endregion 97 | 98 | #region Interop 99 | 100 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] 101 | private static extern IntPtr CreateJobObject(IntPtr a, string lpName); 102 | 103 | [DllImport("kernel32.dll", SetLastError = true)] 104 | private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength); 105 | 106 | [DllImport("kernel32.dll", SetLastError = true)] 107 | private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); 108 | 109 | [DllImport("kernel32.dll", SetLastError = true)] 110 | [return: MarshalAs(UnmanagedType.Bool)] 111 | private static extern bool CloseHandle(IntPtr hObject); 112 | 113 | #endregion 114 | } 115 | 116 | #region Helper classes 117 | 118 | [StructLayout(LayoutKind.Sequential)] 119 | struct IO_COUNTERS 120 | { 121 | public UInt64 ReadOperationCount; 122 | public UInt64 WriteOperationCount; 123 | public UInt64 OtherOperationCount; 124 | public UInt64 ReadTransferCount; 125 | public UInt64 WriteTransferCount; 126 | public UInt64 OtherTransferCount; 127 | } 128 | 129 | 130 | [StructLayout(LayoutKind.Sequential)] 131 | struct JOBOBJECT_BASIC_LIMIT_INFORMATION 132 | { 133 | public Int64 PerProcessUserTimeLimit; 134 | public Int64 PerJobUserTimeLimit; 135 | public UInt32 LimitFlags; 136 | public UIntPtr MinimumWorkingSetSize; 137 | public UIntPtr MaximumWorkingSetSize; 138 | public UInt32 ActiveProcessLimit; 139 | public UIntPtr Affinity; 140 | public UInt32 PriorityClass; 141 | public UInt32 SchedulingClass; 142 | } 143 | 144 | [StructLayout(LayoutKind.Sequential)] 145 | public struct SECURITY_ATTRIBUTES 146 | { 147 | public UInt32 nLength; 148 | public IntPtr lpSecurityDescriptor; 149 | public Int32 bInheritHandle; 150 | } 151 | 152 | [StructLayout(LayoutKind.Sequential)] 153 | struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION 154 | { 155 | public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; 156 | public IO_COUNTERS IoInfo; 157 | public UIntPtr ProcessMemoryLimit; 158 | public UIntPtr JobMemoryLimit; 159 | public UIntPtr PeakProcessMemoryUsed; 160 | public UIntPtr PeakJobMemoryUsed; 161 | } 162 | 163 | public enum JobObjectInfoType 164 | { 165 | AssociateCompletionPortInformation = 7, 166 | BasicLimitInformation = 2, 167 | BasicUIRestrictions = 4, 168 | EndOfJobTimeInformation = 6, 169 | ExtendedLimitInformation = 9, 170 | SecurityLimitInformation = 5, 171 | GroupInformation = 11 172 | } 173 | 174 | #endregion 175 | } 176 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/ProcessManagement/ThreadUtil.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Management; 3 | using System.Text; 4 | 5 | namespace ShadowSocks.Util.ProcessManagement 6 | { 7 | static class ThreadUtil 8 | { 9 | public static string GetCommandLine(this Process process) 10 | { 11 | var commandLine = new StringBuilder(process.MainModule.FileName); 12 | 13 | commandLine.Append(" "); 14 | using (var searcher = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id)) 15 | { 16 | foreach (var @object in searcher.Get()) 17 | { 18 | commandLine.Append(@object["CommandLine"]); 19 | commandLine.Append(" "); 20 | } 21 | } 22 | 23 | return commandLine.ToString(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/Sockets/SocketUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Sockets; 4 | 5 | namespace ShadowSocks.Util.Sockets 6 | { 7 | public static class SocketUtil 8 | { 9 | private class DnsEndPoint2 : DnsEndPoint 10 | { 11 | public DnsEndPoint2(string host, int port) : base(host, port) 12 | { 13 | } 14 | 15 | public DnsEndPoint2(string host, int port, AddressFamily addressFamily) : base(host, port, addressFamily) 16 | { 17 | } 18 | 19 | public override string ToString() 20 | { 21 | return this.Host + ":" + this.Port; 22 | } 23 | } 24 | 25 | public static EndPoint GetEndPoint(string host, int port) 26 | { 27 | IPAddress ipAddress; 28 | bool parsed = IPAddress.TryParse(host, out ipAddress); 29 | if (parsed) 30 | { 31 | return new IPEndPoint(ipAddress, port); 32 | } 33 | 34 | // maybe is a domain name 35 | return new DnsEndPoint2(host, port); 36 | } 37 | 38 | 39 | public static void FullClose(this System.Net.Sockets.Socket s) 40 | { 41 | try 42 | { 43 | s.Shutdown(SocketShutdown.Both); 44 | } 45 | catch (Exception) 46 | { 47 | } 48 | try 49 | { 50 | s.Disconnect(false); 51 | } 52 | catch (Exception) 53 | { 54 | } 55 | try 56 | { 57 | s.Close(); 58 | } 59 | catch (Exception) 60 | { 61 | } 62 | try 63 | { 64 | s.Dispose(); 65 | } 66 | catch (Exception) 67 | { 68 | } 69 | } 70 | 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/SystemProxy/INTERNET_OPTION.cs: -------------------------------------------------------------------------------- 1 | /****************************** Module Header ******************************\ 2 | Module Name: INTERNET_OPTION.cs 3 | Project: CSWebBrowserWithProxy 4 | Copyright (c) Microsoft Corporation. 5 | 6 | This enum contains 4 WinINet constants used in method InternetQueryOption and 7 | InternetSetOption functions. 8 | Visit http://msdn.microsoft.com/en-us/library/aa385328(VS.85).aspx to get the 9 | whole constants list. 10 | 11 | This source is subject to the Microsoft Public License. 12 | See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. 13 | All other rights reserved. 14 | 15 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 16 | EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 18 | \***************************************************************************/ 19 | 20 | namespace ShadowSocks.Util.SystemProxy 21 | { 22 | public enum INTERNET_OPTION 23 | { 24 | // Sets or retrieves an INTERNET_PER_CONN_OPTION_LIST structure that specifies 25 | // a list of options for a particular connection. 26 | INTERNET_OPTION_PER_CONNECTION_OPTION = 75, 27 | 28 | // Notify the system that the registry settings have been changed so that 29 | // it verifies the settings on the next call to InternetConnect. 30 | INTERNET_OPTION_SETTINGS_CHANGED = 39, 31 | 32 | // Causes the proxy data to be reread from the registry for a handle. 33 | INTERNET_OPTION_REFRESH = 37, 34 | 35 | // Alerts the current WinInet instance that proxy settings have changed 36 | // and that they must update with the new settings. 37 | // To alert all available WinInet instances, set the Buffer parameter of 38 | // InternetSetOption to NULL and BufferLength to 0 when passing this option. 39 | INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 95 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION.cs: -------------------------------------------------------------------------------- 1 | /****************************** Module Header ******************************\ 2 | Module Name: INTERNET_PER_CONN_OPTION.cs 3 | Project: CSWebBrowserWithProxy 4 | Copyright (c) Microsoft Corporation. 5 | 6 | This file defines the struct INTERNET_PER_CONN_OPTION and constants used by it. 7 | The struct INTERNET_PER_CONN_OPTION contains the value of an option that to be 8 | set to internet settings. 9 | Visit http://msdn.microsoft.com/en-us/library/aa385145(VS.85).aspx to get the 10 | detailed description. 11 | 12 | This source is subject to the Microsoft Public License. 13 | See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. 14 | All other rights reserved. 15 | 16 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 17 | EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 19 | \***************************************************************************/ 20 | 21 | using System; 22 | using System.Runtime.InteropServices; 23 | 24 | namespace ShadowSocks.Util.SystemProxy 25 | { 26 | /// 27 | /// Constants used in INTERNET_PER_CONN_OPTION_OptionUnion struct. 28 | /// 29 | public enum INTERNET_PER_CONN_OptionEnum 30 | { 31 | INTERNET_PER_CONN_FLAGS = 1, 32 | INTERNET_PER_CONN_PROXY_SERVER = 2, 33 | INTERNET_PER_CONN_PROXY_BYPASS = 3, 34 | INTERNET_PER_CONN_AUTOCONFIG_URL = 4, 35 | INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5, 36 | INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL = 6, 37 | INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = 7, 38 | INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = 8, 39 | INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = 9, 40 | INTERNET_PER_CONN_FLAGS_UI = 10 41 | } 42 | 43 | /// 44 | /// Constants used in INTERNET_PER_CONN_OPTON struct. 45 | /// 46 | [Flags] 47 | public enum INTERNET_OPTION_PER_CONN_FLAGS 48 | { 49 | PROXY_TYPE_DIRECT = 0x00000001, // direct to net 50 | PROXY_TYPE_PROXY = 0x00000002, // via named proxy 51 | PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL 52 | PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection 53 | } 54 | 55 | /// 56 | /// Constants used in INTERNET_PER_CONN_OPTON struct. 57 | /// Windows 7 and later: 58 | /// Clients that support Internet Explorer 8 should query the connection type using INTERNET_PER_CONN_FLAGS_UI. 59 | /// If this query fails, then the system is running a previous version of Internet Explorer and the client should 60 | /// query again with INTERNET_PER_CONN_FLAGS. 61 | /// Restore the connection type using INTERNET_PER_CONN_FLAGS regardless of the version of Internet Explorer. 62 | /// XXX: If fails, notify user to upgrade Internet Explorer 63 | /// 64 | [Flags] 65 | public enum INTERNET_OPTION_PER_CONN_FLAGS_UI 66 | { 67 | PROXY_TYPE_DIRECT = 0x00000001, // direct to net 68 | PROXY_TYPE_PROXY = 0x00000002, // via named proxy 69 | PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL 70 | PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection 71 | } 72 | 73 | /// 74 | /// Used in INTERNET_PER_CONN_OPTION. 75 | /// When create a instance of OptionUnion, only one filed will be used. 76 | /// The StructLayout and FieldOffset attributes could help to decrease the struct size. 77 | /// 78 | [StructLayout(LayoutKind.Explicit)] 79 | public struct INTERNET_PER_CONN_OPTION_OptionUnion : IDisposable 80 | { 81 | // A value in INTERNET_OPTION_PER_CONN_FLAGS. 82 | [FieldOffset(0)] 83 | public int dwValue; 84 | [FieldOffset(0)] 85 | public System.IntPtr pszValue; 86 | [FieldOffset(0)] 87 | public System.Runtime.InteropServices.ComTypes.FILETIME ftValue; 88 | 89 | public void Dispose() 90 | { 91 | Dispose(true); 92 | GC.SuppressFinalize(this); 93 | } 94 | 95 | private void Dispose(bool disposing) 96 | { 97 | if (disposing) 98 | { 99 | if (pszValue != IntPtr.Zero) 100 | { 101 | Marshal.FreeHGlobal(pszValue); 102 | pszValue = IntPtr.Zero; 103 | } 104 | } 105 | } 106 | } 107 | 108 | [StructLayout(LayoutKind.Sequential)] 109 | public struct INTERNET_PER_CONN_OPTION 110 | { 111 | // A value in INTERNET_PER_CONN_OptionEnum. 112 | public int dwOption; 113 | public INTERNET_PER_CONN_OPTION_OptionUnion Value; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION_LIST.cs: -------------------------------------------------------------------------------- 1 | /****************************** Module Header ******************************\ 2 | Module Name: INTERNET_PER_CONN_OPTION_LIST.cs 3 | Project: CSWebBrowserWithProxy 4 | Copyright (c) Microsoft Corporation. 5 | 6 | The struct INTERNET_PER_CONN_OPTION contains a list of options that to be 7 | set to internet connection. 8 | Visit http://msdn.microsoft.com/en-us/library/aa385146(VS.85).aspx to get the 9 | detailed description. 10 | 11 | This source is subject to the Microsoft Public License. 12 | See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. 13 | All other rights reserved. 14 | 15 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 16 | EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 18 | \***************************************************************************/ 19 | 20 | using System; 21 | using System.Runtime.InteropServices; 22 | 23 | namespace ShadowSocks.Util.SystemProxy 24 | { 25 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 26 | public struct INTERNET_PER_CONN_OPTION_LIST : IDisposable 27 | { 28 | public int Size; 29 | 30 | // The connection to be set. NULL means LAN. 31 | public System.IntPtr Connection; 32 | 33 | public int OptionCount; 34 | public int OptionError; 35 | 36 | // List of INTERNET_PER_CONN_OPTIONs. 37 | public System.IntPtr pOptions; 38 | 39 | public void Dispose() 40 | { 41 | Dispose( true ); 42 | GC.SuppressFinalize( this ); 43 | } 44 | 45 | private void Dispose( bool disposing ) 46 | { 47 | if ( disposing ) 48 | { 49 | if ( Connection != IntPtr.Zero ) 50 | { 51 | Marshal.FreeHGlobal( Connection ); 52 | Connection = IntPtr.Zero; 53 | } 54 | 55 | if ( pOptions != IntPtr.Zero ) 56 | { 57 | Marshal.FreeHGlobal( pOptions ); 58 | pOptions = IntPtr.Zero; 59 | } 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/SystemProxy/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | /****************************** Module Header ******************************\ 2 | Module Name: NativeMethods.cs 3 | Project: CSWebBrowserWithProxy 4 | Copyright (c) Microsoft Corporation. 5 | 6 | This class is a simple .NET wrapper of wininet.dll. It contains 4 extern 7 | methods in wininet.dll. They are InternetOpen, InternetCloseHandle, 8 | InternetSetOption and InternetQueryOption. 9 | 10 | This source is subject to the Microsoft Public License. 11 | See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. 12 | All other rights reserved. 13 | 14 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 15 | EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 17 | \***************************************************************************/ 18 | 19 | using System; 20 | using System.Runtime.InteropServices; 21 | 22 | namespace ShadowSocks.Util.SystemProxy 23 | { 24 | internal static class NativeMethods 25 | { 26 | /// 27 | /// Sets an Internet option. 28 | /// 29 | [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] 30 | internal static extern bool InternetSetOption( 31 | IntPtr hInternet, 32 | INTERNET_OPTION dwOption, 33 | IntPtr lpBuffer, 34 | int lpdwBufferLength); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/SystemProxy/ProxyException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace ShadowSocks.Util.SystemProxy 9 | { 10 | class ProxyException : Exception 11 | { 12 | public ProxyException() 13 | { 14 | } 15 | 16 | public ProxyException(string message) : base(message) 17 | { 18 | } 19 | 20 | public ProxyException(string message, Exception innerException) : base(message, innerException) 21 | { 22 | } 23 | 24 | protected ProxyException(SerializationInfo info, StreamingContext context) : base(info, context) 25 | { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/SystemProxy/RAS.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace ShadowSocks.Util.SystemProxy 4 | { 5 | internal static class RemoteAccessService 6 | { 7 | private enum RasFieldSizeConstants 8 | { 9 | #region original header 10 | 11 | //#if (WINVER >= 0x400) 12 | //#define RAS_MaxEntryName 256 13 | //#define RAS_MaxDeviceName 128 14 | //#define RAS_MaxCallbackNumber RAS_MaxPhoneNumber 15 | //#else 16 | //#define RAS_MaxEntryName 20 17 | //#define RAS_MaxDeviceName 32 18 | //#define RAS_MaxCallbackNumber 48 19 | //#endif 20 | 21 | #endregion 22 | 23 | RAS_MaxEntryName = 256, 24 | RAS_MaxPath = 260 25 | } 26 | 27 | private const int ERROR_SUCCESS = 0; 28 | private const int RASBASE = 600; 29 | private const int ERROR_BUFFER_TOO_SMALL = RASBASE + 3; 30 | 31 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 32 | private struct RasEntryName 33 | { 34 | #region original header 35 | 36 | //#define RASENTRYNAMEW struct tagRASENTRYNAMEW 37 | //RASENTRYNAMEW 38 | //{ 39 | // DWORD dwSize; 40 | // WCHAR szEntryName[RAS_MaxEntryName + 1]; 41 | // 42 | //#if (WINVER >= 0x500) 43 | // // 44 | // // If this flag is REN_AllUsers then its a 45 | // // system phonebook. 46 | // // 47 | // DWORD dwFlags; 48 | // WCHAR szPhonebookPath[MAX_PATH + 1]; 49 | //#endif 50 | //}; 51 | // 52 | //#define RASENTRYNAMEA struct tagRASENTRYNAMEA 53 | //RASENTRYNAMEA 54 | //{ 55 | // DWORD dwSize; 56 | // CHAR szEntryName[RAS_MaxEntryName + 1]; 57 | // 58 | //#if (WINVER >= 0x500) 59 | // DWORD dwFlags; 60 | // CHAR szPhonebookPath[MAX_PATH + 1]; 61 | //#endif 62 | //}; 63 | 64 | #endregion 65 | 66 | public int dwSize; 67 | 68 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst=(int)RasFieldSizeConstants.RAS_MaxEntryName + 1)] 69 | public string szEntryName; 70 | 71 | public int dwFlags; 72 | 73 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst=(int)RasFieldSizeConstants.RAS_MaxPath + 1)] 74 | public string szPhonebookPath; 75 | } 76 | 77 | [DllImport("rasapi32.dll", CharSet = CharSet.Auto)] 78 | private static extern uint RasEnumEntries( 79 | // reserved, must be NULL 80 | string reserved, 81 | // pointer to full path and file name of phone-book file 82 | string lpszPhonebook, 83 | // buffer to receive phone-book entries 84 | [In, Out] RasEntryName[] lprasentryname, 85 | // size in bytes of buffer 86 | ref int lpcb, 87 | // number of entries written to buffer 88 | out int lpcEntries 89 | ); 90 | 91 | /// 92 | /// Get all entries from RAS 93 | /// 94 | /// 95 | /// 96 | /// 0: success with entries 97 | /// 1: success but no entries found 98 | /// 2: failed 99 | /// 100 | public static uint GetAllConns(ref string[] allConns) 101 | { 102 | int lpNames = 0; 103 | int entryNameSize = 0; 104 | int lpSize = 0; 105 | uint retval = ERROR_SUCCESS; 106 | RasEntryName[] names = null; 107 | 108 | entryNameSize = Marshal.SizeOf(typeof(RasEntryName)); 109 | 110 | // Windows Vista or later: To determine the required buffer size, call RasEnumEntries 111 | // with lprasentryname set to NULL. The variable pointed to by lpcb should be set to zero. 112 | // The function will return the required buffer size in lpcb and an error code of ERROR_BUFFER_TOO_SMALL. 113 | retval = RasEnumEntries(null, null, null, ref lpSize, out lpNames); 114 | 115 | if (retval == ERROR_BUFFER_TOO_SMALL) 116 | { 117 | names = new RasEntryName[lpNames]; 118 | for (int i = 0; i < names.Length; i++) 119 | { 120 | names[i].dwSize = entryNameSize; 121 | } 122 | 123 | retval = RasEnumEntries(null, null, names, ref lpSize, out lpNames); 124 | } 125 | 126 | if (retval == ERROR_SUCCESS) 127 | { 128 | if (lpNames == 0) 129 | { 130 | // no entries found. 131 | return 1; 132 | } 133 | 134 | allConns = new string[names.Length]; 135 | 136 | for (int i = 0; i < names.Length; i++) 137 | { 138 | allConns[i] = names[i].szEntryName; 139 | } 140 | return 0; 141 | } 142 | else 143 | { 144 | return 2; 145 | } 146 | } 147 | } 148 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/ValidateHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace ShadowSocks.Util 5 | { 6 | public static class ValidateHelper 7 | { 8 | public static bool PhoneValidator(String phone) { 9 | Regex r = new Regex(@"^(13[0-9]|147|15[0-9]|17[0-9]|18[0-9])\d{8}$"); 10 | Match m = r.Match(phone); 11 | if (m.Success){ 12 | return true; 13 | } 14 | return false; 15 | } 16 | 17 | public static bool PasswordValidator(String password) { 18 | Regex r = new Regex(@"^[A-Za-z0-9_]{6,30}$"); 19 | Match m = r.Match(password); 20 | if (m.Success) 21 | { 22 | return true; 23 | } 24 | return false; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /shadowsocks-csharp/Util/ViewUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Windows.Forms; 6 | 7 | namespace ShadowSocks.Util 8 | { 9 | public static class ViewUtils 10 | { 11 | public static IEnumerable GetChildControls(this Control control) where TControl : Control 12 | { 13 | if (control.Controls.Count == 0) 14 | { 15 | return Enumerable.Empty(); 16 | } 17 | 18 | var children = control.Controls.OfType().ToList(); 19 | return children.SelectMany(GetChildControls).Concat(children); 20 | } 21 | 22 | // Workaround NotifyIcon's 63 chars limit 23 | // https://stackoverflow.com/questions/579665/how-can-i-show-a-systray-tooltip-longer-than-63-chars 24 | public static void SetNotifyIconText(NotifyIcon ni, string text) 25 | { 26 | if (text.Length >= 128) 27 | throw new ArgumentOutOfRangeException("Text limited to 127 characters"); 28 | Type t = typeof(NotifyIcon); 29 | BindingFlags hidden = BindingFlags.NonPublic | BindingFlags.Instance; 30 | t.GetField("text", hidden).SetValue(ni, text); 31 | if ((bool)t.GetField("added", hidden).GetValue(ni)) 32 | t.GetMethod("UpdateIcon", hidden).Invoke(ni, new object[] { true }); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /shadowsocks-csharp/View/Notice.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ShadowSocks.View 2 | { 3 | partial class Notice 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Notice)); 32 | this.lblWindowTitle = new System.Windows.Forms.Label(); 33 | this.SuspendLayout(); 34 | // 35 | // lblWindowTitle 36 | // 37 | this.lblWindowTitle.AutoSize = true; 38 | this.lblWindowTitle.BackColor = System.Drawing.Color.Transparent; 39 | this.lblWindowTitle.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 40 | this.lblWindowTitle.ForeColor = System.Drawing.Color.White; 41 | this.lblWindowTitle.Location = new System.Drawing.Point(11, 10); 42 | this.lblWindowTitle.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); 43 | this.lblWindowTitle.Name = "lblWindowTitle"; 44 | this.lblWindowTitle.Size = new System.Drawing.Size(92, 27); 45 | this.lblWindowTitle.TabIndex = 1; 46 | this.lblWindowTitle.Text = "系统通知"; 47 | // 48 | // Notice 49 | // 50 | this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 24F); 51 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 52 | this.ClientSize = new System.Drawing.Size(400, 400); 53 | this.Controls.Add(this.lblWindowTitle); 54 | this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 55 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 56 | this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); 57 | this.Name = "Notice"; 58 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 59 | this.ResumeLayout(false); 60 | this.PerformLayout(); 61 | 62 | } 63 | 64 | #endregion 65 | 66 | private System.Windows.Forms.Label lblWindowTitle; 67 | } 68 | } -------------------------------------------------------------------------------- /shadowsocks-csharp/View/Notice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | using MaterialSkin; 12 | using MaterialSkin.Controls; 13 | 14 | namespace ShadowSocks.View 15 | { 16 | public partial class Notice : MaterialForm 17 | { 18 | private readonly MaterialSkinManager materialSkinManager; 19 | 20 | public Notice() 21 | { 22 | InitializeComponent(); 23 | 24 | materialSkinManager = MaterialSkinManager.Instance; 25 | materialSkinManager.AddFormToManage(this); 26 | materialSkinManager.Theme = MaterialSkinManager.Themes.LIGHT; 27 | materialSkinManager.ColorScheme = new ColorScheme(Primary.LightBlue500, Primary.LightBlue500, Primary.Amber900, Accent.Amber700, TextShade.WHITE); 28 | 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /shadowsocks-csharp/View/ViewManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using ShadowSocks.Controller; 7 | using System.Windows.Forms; 8 | 9 | namespace ShadowSocks.View 10 | { 11 | public class ViewManager 12 | { 13 | 14 | private static ViewManager viewManager; 15 | 16 | private Main mainForm; 17 | private Log logForm; 18 | private Setting settingForm; 19 | private Login loginForm; 20 | private Notice noticeForm; 21 | 22 | private MenuViewController menuController; 23 | private ShadowSocksController mainController; 24 | 25 | public ViewManager() 26 | { 27 | } 28 | 29 | public static ViewManager instance 30 | { 31 | get 32 | { 33 | if (viewManager == null) 34 | { 35 | viewManager = new ViewManager(); 36 | } 37 | return viewManager; 38 | } 39 | } 40 | 41 | public ShadowSocksController MainController { 42 | get 43 | { 44 | if (mainController == null) 45 | { 46 | mainController = ShadowSocksController.instance(); 47 | } 48 | return mainController; 49 | } 50 | } 51 | 52 | public MenuViewController MenuController { 53 | get 54 | { 55 | if (menuController == null) 56 | { 57 | menuController = new MenuViewController(); 58 | } 59 | return menuController; 60 | } 61 | } 62 | 63 | public Main MainForm { 64 | get { 65 | if (this.mainForm == null || this.mainForm.IsDisposed) 66 | { 67 | this.mainForm = new Main(); 68 | } 69 | return mainForm; 70 | } 71 | } 72 | 73 | public Login LoginForm { 74 | get 75 | { 76 | if (this.loginForm == null || this.loginForm.IsDisposed) 77 | { 78 | this.loginForm = new Login(); 79 | } 80 | return loginForm; 81 | } 82 | } 83 | 84 | public Setting SettingForm 85 | { 86 | get 87 | { 88 | if (this.settingForm == null || this.settingForm.IsDisposed) 89 | { 90 | this.settingForm = new Setting(); 91 | } 92 | return settingForm; 93 | } 94 | } 95 | 96 | public Log LogForm 97 | { 98 | get 99 | { 100 | if (this.logForm == null || this.logForm.IsDisposed) 101 | { 102 | this.logForm = new Log(); 103 | } 104 | return logForm; 105 | } 106 | } 107 | 108 | public Notice NoticeForm 109 | { 110 | get 111 | { 112 | if (this.noticeForm == null || this.noticeForm.IsDisposed) 113 | { 114 | this.noticeForm = new Notice(); 115 | } 116 | return noticeForm; 117 | } 118 | } 119 | 120 | 121 | public void showMainForm() { 122 | this.MainForm.Show(); 123 | this.MainForm.Activate(); 124 | this.MainForm.WindowState = FormWindowState.Normal; 125 | this.MainForm.BringToFront(); 126 | } 127 | 128 | public void closeMainForm() { 129 | if (mainForm!=null) 130 | { 131 | mainForm.Hide(); 132 | } 133 | } 134 | 135 | public void showLoginForm() 136 | { 137 | this.LoginForm.Show(); 138 | this.LoginForm.Activate(); 139 | this.LoginForm.WindowState = FormWindowState.Normal; 140 | this.LoginForm.BringToFront(); 141 | } 142 | 143 | public void closeLoginForm() { 144 | if (loginForm!=null) 145 | { 146 | loginForm.Hide(); 147 | } 148 | } 149 | 150 | public void showLogForm() 151 | { 152 | this.LogForm.Show(); 153 | this.LogForm.Activate(); 154 | this.LogForm.WindowState = FormWindowState.Normal; 155 | this.LogForm.BringToFront(); 156 | } 157 | 158 | public void closeLogForm() 159 | { 160 | if (logForm!=null) 161 | { 162 | logForm.Hide(); 163 | } 164 | } 165 | 166 | public void showSettingForm() 167 | { 168 | this.SettingForm.Show(); 169 | this.SettingForm.Activate(); 170 | this.SettingForm.WindowState = FormWindowState.Normal; 171 | this.SettingForm.BringToFront(); 172 | } 173 | 174 | public void showNoticeForm() { 175 | this.NoticeForm.Show(); 176 | this.NoticeForm.Activate(); 177 | this.NoticeForm.WindowState = FormWindowState.Normal; 178 | this.NoticeForm.BringToFront(); 179 | } 180 | 181 | public void closeSettingForm() 182 | { 183 | if (settingForm!=null) 184 | { 185 | settingForm.Hide(); 186 | } 187 | } 188 | 189 | public void closeNoticeForm() { 190 | if (noticeForm != null) 191 | { 192 | noticeForm.Hide(); 193 | } 194 | } 195 | 196 | public void closeMainController() { 197 | if (mainController!=null) 198 | { 199 | mainController.Stop(); 200 | mainController = null; 201 | } 202 | } 203 | 204 | public void controlNotifyTray(bool visiable) { 205 | if (menuController!=null) 206 | { 207 | menuController.controlNotifyTray(visiable); 208 | } 209 | if (visiable == false) 210 | { 211 | menuController = null; 212 | } 213 | } 214 | 215 | public void showBalloonTip(string title, string content, ToolTipIcon icon, int timeout) { 216 | if (menuController!=null) 217 | { 218 | menuController.showBalloonTip(title, content, icon, timeout); 219 | } 220 | } 221 | 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /shadowsocks-csharp/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 0 42 | 43 | 44 | 45 | 46 | 47 | 0 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 0 60 | 61 | 62 | 0 63 | 64 | 65 | 0 66 | 67 | 68 | 0 69 | 70 | 71 | False 72 | 73 | 74 | 0 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /shadowsocks-csharp/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /shadowsocks-csharp/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/logo.ico -------------------------------------------------------------------------------- /shadowsocks-csharp/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenuuu/greendot-windows/7b86d402bd0d33a78e5ffa91da9ba93256951e51/shadowsocks-csharp/logo.png -------------------------------------------------------------------------------- /shadowsocks-csharp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /shadowsocks-csharp/shadowsocks-csharp.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ProjectFiles 5 | publish\ 6 | 7 | 8 | 9 | 10 | 11 | zh-CN 12 | false 13 | 14 | --------------------------------------------------------------------------------