Skip to content

Commit

Permalink
Merge pull request #2008 from studentmain/master
Browse files Browse the repository at this point in the history
Improve sysproxy exception handling
  • Loading branch information
celeron533 committed Oct 7, 2018
2 parents 7e21e16 + 572f53a commit 91f0bf6
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 20 deletions.
19 changes: 19 additions & 0 deletions shadowsocks-csharp/Controller/Logging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics;
using System.Text;
using Shadowsocks.Util;
using Shadowsocks.Util.SystemProxy;

namespace Shadowsocks.Controller
{
Expand Down Expand Up @@ -145,6 +146,24 @@ public static void LogUsefulException(Exception e)
{
Info(e);
}
}
else if (e is ProxyException)
{
var ex = (ProxyException)e;
switch (ex.Type)
{
case ProxyExceptionType.FailToRun:
case ProxyExceptionType.QueryReturnMalformed:
case ProxyExceptionType.SysproxyExitError:
Error($"sysproxy - {ex.Type.ToString()}:{ex.Message}");
break;
case ProxyExceptionType.QueryReturnEmpty:
case ProxyExceptionType.Unspecific:
Error($"sysproxy - {ex.Type.ToString()}");
break;
}


}
else
{
Expand Down
16 changes: 15 additions & 1 deletion shadowsocks-csharp/Controller/System/SystemProxy.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Windows.Forms;
using Shadowsocks.Model;
using Shadowsocks.Util.SystemProxy;

Expand All @@ -11,7 +12,7 @@ private static string GetTimestamp(DateTime value)
return value.ToString("yyyyMMddHHmmssfff");
}

public static void Update(Configuration config, bool forceDisable, PACServer pacSrv)
public static void Update(Configuration config, bool forceDisable, PACServer pacSrv, bool noRetry = false)
{
bool global = config.global;
bool enabled = config.enabled;
Expand Down Expand Up @@ -51,6 +52,19 @@ public static void Update(Configuration config, bool forceDisable, PACServer pac
catch (ProxyException ex)
{
Logging.LogUsefulException(ex);
if (ex.Type != ProxyExceptionType.Unspecific && !noRetry)
{
var ret = MessageBox.Show(I18N.GetString("Error occured when process proxy setting, do you want reset current setting and retry?"), I18N.GetString("Shadowsocks"), MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (ret == DialogResult.Yes)
{
Sysproxy.ResetIEProxy();
Update(config, forceDisable, pacSrv, true);
}
}
else
{
MessageBox.Show(I18N.GetString("Unrecoverable proxy setting error occured, see log for detail"), I18N.GetString("Shadowsocks"), MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion shadowsocks-csharp/Data/ja.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,4 @@ Proxy request failed=プロキシ要求が失敗しました。
Proxy handshake failed=プロキシ ハンドシェイクに失敗しました。
Register hotkey failed=ホットキーの登錄に失敗しました。
Cannot parse hotkey: {0}=ホットキーを解析できません: {0}
Timeout is invalid, it should not exceed {0}=タイムアウト値が無効です。{0} 以下の値を指定して下さい。
Timeout is invalid, it should not exceed {0}=タイムアウト値が無効です。{0} 以下の値を指定して下さい。
3 changes: 3 additions & 0 deletions shadowsocks-csharp/Data/zh_CN.txt
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,6 @@ Proxy handshake failed=代理握手失败
Register hotkey failed=注册快捷键失败
Cannot parse hotkey: {0}=解析快捷键失败: {0}
Timeout is invalid, it should not exceed {0}=超时无效,不应超过 {0}

Error occured when process proxy setting, do you want reset current setting and retry?=处理代理设置时发生错误,是否重置当前代理设置并重试?
Unrecoverable proxy setting error occured, see log for detail=发生不可恢复的代理设置错误,查看日志以取得详情
2 changes: 1 addition & 1 deletion shadowsocks-csharp/Data/zh_TW.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,4 @@ Proxy request failed=Proxy 要求失敗
Proxy handshake failed=Proxy 交握失敗
Register hotkey failed=註冊快速鍵失敗
Cannot parse hotkey: {0}=剖析快速鍵失敗: {0}
Timeout is invalid, it should not exceed {0}=逾時無效,不應超過 {0}
Timeout is invalid, it should not exceed {0}=逾時無效,不應超過 {0}
31 changes: 31 additions & 0 deletions shadowsocks-csharp/Util/SystemProxy/ProxyException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,20 @@

namespace Shadowsocks.Util.SystemProxy
{
enum ProxyExceptionType
{
Unspecific,
FailToRun,
QueryReturnEmpty,
SysproxyExitError,
QueryReturnMalformed
}

class ProxyException : Exception
{
// provide more specific information about exception
public ProxyExceptionType Type { get; }

public ProxyException()
{
}
Expand All @@ -24,5 +36,24 @@ public ProxyException(string message, Exception innerException) : base(message,
protected ProxyException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
public ProxyException(ProxyExceptionType type)
{
this.Type = type;
}

public ProxyException(ProxyExceptionType type, string message) : base(message)
{
this.Type = type;
}

public ProxyException(ProxyExceptionType type, string message, Exception innerException) : base(message, innerException)
{
this.Type = type;
}

protected ProxyException(ProxyExceptionType type, SerializationInfo info, StreamingContext context) : base(info, context)
{
this.Type = type;
}
}
}
81 changes: 64 additions & 17 deletions shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System;
using Newtonsoft.Json;
using Shadowsocks.Controller;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using Shadowsocks.Controller;
using Shadowsocks.Properties;
using Shadowsocks.Model;
using Newtonsoft.Json;

namespace Shadowsocks.Util.SystemProxy
{
Expand Down Expand Up @@ -82,6 +82,26 @@ public static void SetIEProxy(bool enable, bool global, string proxyServer, stri
ExecSysproxy(arguments);
}


// set system proxy to 1 (null) (null) (null)
public static bool ResetIEProxy()
{
try
{
// clear user-wininet.json
_userSettings = new SysproxyConfig();
Save();
// clear system setting
ExecSysproxy("set 1 - - -");
}
catch (Exception e)
{
return false;
}

return true;
}

private static void ExecSysproxy(string arguments)
{
// using event to avoid hanging when redirect standard output/error
Expand Down Expand Up @@ -132,27 +152,35 @@ private static void ExecSysproxy(string arguments)
error.AppendLine(e.Data);
}
};
try
{
process.Start();

process.Start();

process.BeginErrorReadLine();
process.BeginOutputReadLine();

process.WaitForExit();
process.BeginErrorReadLine();
process.BeginOutputReadLine();

process.WaitForExit();
}
catch (System.ComponentModel.Win32Exception e)
{
// log the arguements
throw new ProxyException(ProxyExceptionType.FailToRun, process.StartInfo.Arguments, e);
}
var stderr = error.ToString();
var stdout = output.ToString();

var exitCode = process.ExitCode;
if (exitCode != (int)RET_ERRORS.RET_NO_ERROR)
{
throw new ProxyException(stderr);
throw new ProxyException(ProxyExceptionType.SysproxyExitError, stderr);
}

if (arguments == "query") {
if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty()) {
if (arguments == "query")
{
if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty())
{
// we cannot get user settings
throw new ProxyException("failed to query wininet settings");
throw new ProxyException(ProxyExceptionType.QueryReturnEmpty);
}
_queryStr = stdout;
}
Expand Down Expand Up @@ -183,16 +211,35 @@ private static void Read()
{
string configContent = File.ReadAllText(Utils.GetTempPath(_userWininetConfigFile));
_userSettings = JsonConvert.DeserializeObject<SysproxyConfig>(configContent);
} catch(Exception) {
}
catch (Exception)
{
// Suppress all exceptions. finally block will initialize new user config settings.
} finally {
}
finally
{
if (_userSettings == null) _userSettings = new SysproxyConfig();
}
}

private static void ParseQueryStr(string str)
{
string[] userSettingsArr = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

// sometimes sysproxy output in utf16le instead of ascii
// manually translate it
if (userSettingsArr.Length != 4)
{
byte[] strByte = Encoding.ASCII.GetBytes(str);
str = Encoding.Unicode.GetString(strByte);
userSettingsArr = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
// still fail, throw exception with string hexdump
if (userSettingsArr.Length != 4)
{
throw new ProxyException(ProxyExceptionType.QueryReturnMalformed, BitConverter.ToString(strByte));
}
}

_userSettings.Flags = userSettingsArr[0];

// handle output from WinINET
Expand Down

0 comments on commit 91f0bf6

Please sign in to comment.