Compare commits

..
8 Commits
Author SHA1 Message Date
Syrone Wong e9ba34373b Update CHANGES and bump version
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2017-01-11 14:27:24 +08:00
Syrone Wong 4c49f1b736 Make the previous portable mode as default
- change dir name to "ss_win_temp" to make things clear.
- throw any exception caught when creating temp folder

To workaround silly cleaning softwares and careless users.

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2017-01-11 14:05:11 +08:00
破娃酱 b266bf42f5 create "help" menu group (#989) 2017-01-08 08:44:49 +08:00
Noisyfox 2e7518d802 Send first chunk with Socks5 header (#984)
* Send socks5 handshake respond before read the target address
So that the next package will (hopefully) contain the first data chunk which means we could get a 'random' first package size.

* Try read available data before send first packet

* Add random size first packet
But commented out ^u^

* Oops forget to delete some test code
2017-01-04 07:59:41 +08:00
破娃酱 18e956f34c not set alpha of the icon (#981) 2017-01-02 15:19:23 +08:00
Syrone Wong 333ad2516f Fix language detection
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-12-31 19:35:37 +08:00
Syrone Wong 9ffcf77ab1 Update LICENSE
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-12-31 16:25:41 +08:00
Syrone Wong d0d6a3cdfa Happy New Year
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-12-31 11:11:45 +08:00
12 changed files with 155 additions and 147 deletions
+5
View File
@@ -1,3 +1,8 @@
3.4.3 2017-1-11
- Make the previous portable mode as default
- Refine networking by Noisyfox
- Bug fixes and improvements
3.4.2.1 2016-12-30
- Refine Traditional Chinese translation by LNDDYL
- sysproxy: reduce false positives on virus detection
+19 -19
View File
@@ -994,31 +994,31 @@ https://tls.mbed.org
License: https://raw.githubusercontent.com/ARMmbed/mbedtls/master/LICENSE
SimpleJson
Newtonsoft.Json
----------
https://github.com/facebook-csharp-sdk/simple-json
https://raw.githubusercontent.com/JamesNK/Newtonsoft.Json/master/LICENSE.md
Copyright (c) 2011, The Outercurve Foundation
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
Copyright (c) 2007 James Newton-King
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ZXing
-5
View File
@@ -89,11 +89,6 @@ if you want to deactivate all, please clear all textboxes.
Please visit [Servers] for more information.
#### Portable Mode
If you want to put all temporary files into shadowsocks/temp folder instead of
system temp folder, create a `shadowsocks_portable_mode.txt` into shadowsocks folder.
#### Develop
[Visual Studio 2015] & [.NET Framework 4.6.2 Developer Pack] are required.
+13 -23
View File
@@ -7,11 +7,11 @@ namespace Shadowsocks.Controller
{
using Shadowsocks.Properties;
public class I18N
public static class I18N
{
protected static Dictionary<string, string> Strings;
private static Dictionary<string, string> _strings = new Dictionary<string, string>();
static void Init(string res)
private static void Init(string res)
{
using (var sr = new StringReader(res))
{
@@ -23,38 +23,28 @@ namespace Shadowsocks.Controller
var pos = line.IndexOf('=');
if (pos < 1)
continue;
Strings[line.Substring(0, pos)] = line.Substring(pos + 1);
_strings[line.Substring(0, pos)] = line.Substring(pos + 1);
}
}
}
static I18N()
{
Strings = new Dictionary<string, string>();
string name = CultureInfo.CurrentCulture.Name;
if (name.StartsWith("zh"))
string name = CultureInfo.CurrentCulture.EnglishName;
if (name.StartsWith("Chinese", StringComparison.OrdinalIgnoreCase))
{
if (name == "zh" || name == "zh-CN")
{
Init(Resources.cn);
}
else
{
Init(Resources.zh_tw);
}
// choose Traditional Chinese only if we get explicit indication
Init(name.Contains("Traditional")
? Resources.zh_tw
: Resources.cn);
}
}
public static string GetString(string key)
{
if (Strings.ContainsKey(key))
{
return Strings[key];
}
else
{
return key;
}
return _strings.ContainsKey(key)
? _strings[key]
: key;
}
}
}
@@ -121,21 +121,13 @@ namespace Shadowsocks.Controller
{
try
{
if (Utils.IsPortableMode())
{
/*
* Under PortableMode, we could identify it by the path of ss_privoxy.exe.
*/
var path = process.MainModule.FileName;
/*
* Under PortableMode, we could identify it by the path of ss_privoxy.exe.
*/
var path = process.MainModule.FileName;
return Utils.GetTempPath("ss_privoxy.exe").Equals(path);
}
else
{
var cmd = process.GetCommandLine();
return Utils.GetTempPath("ss_privoxy.exe").Equals(path);
return cmd.Contains(_uniqueConfigFile);
}
}
catch (Exception ex)
{
@@ -322,24 +322,15 @@ namespace Shadowsocks.Controller
}
else
{
int atyp = _connetionRecvBuffer[3];
switch (atyp)
if (_command == 1)
{
case 1: // IPv4 address, 4 bytes
ReadAddress(4 + 2 - 1);
break;
case 3: // domain name, length + str
int len = _connetionRecvBuffer[4];
ReadAddress(len + 2);
break;
case 4: // IPv6 address, 16 bytes
ReadAddress(16 + 2 - 1);
break;
default:
Logging.Debug("Unsupported ATYP=" + atyp);
Close();
break;
byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
_connection.BeginSend(response, 0, response.Length, SocketFlags.None,
new AsyncCallback(ResponseCallback), null);
}
else if (_command == 3)
{
ReadAddress(HandleUDPAssociate);
}
}
}
@@ -356,12 +347,50 @@ namespace Shadowsocks.Controller
}
}
private void ReadAddress(int bytesRemain)
private void ResponseCallback(IAsyncResult ar)
{
try
{
_connection.EndSend(ar);
ReadAddress(StartConnect);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
Close();
}
}
private void ReadAddress(Action onSuccess)
{
int atyp = _connetionRecvBuffer[3];
switch (atyp)
{
case 1: // IPv4 address, 4 bytes
ReadAddress(4 + 2 - 1, onSuccess);
break;
case 3: // domain name, length + str
int len = _connetionRecvBuffer[4];
ReadAddress(len + 2, onSuccess);
break;
case 4: // IPv6 address, 16 bytes
ReadAddress(16 + 2 - 1, onSuccess);
break;
default:
Logging.Debug("Unsupported ATYP=" + atyp);
Close();
break;
}
}
private void ReadAddress(int bytesRemain, Action onSuccess)
{
Array.Copy(_connetionRecvBuffer, 3, _connetionRecvBuffer, 0, 2);
// Read the remain address bytes
_connection.BeginReceive(_connetionRecvBuffer, 2, RecvSize - 2, SocketFlags.None, OnAddressFullyRead, bytesRemain);
_connection.BeginReceive(_connetionRecvBuffer, 2, RecvSize - 2, SocketFlags.None, OnAddressFullyRead, new object[] {bytesRemain, onSuccess});
}
private void OnAddressFullyRead(IAsyncResult ar)
@@ -370,7 +399,12 @@ namespace Shadowsocks.Controller
try
{
int bytesRead = _connection.EndReceive(ar);
int bytesRemain = (int) ar.AsyncState;
var states = (object[]) ar.AsyncState;
int bytesRemain = (int)states[0];
var onSuccess = (Action) states[1];
if (bytesRead >= bytesRemain)
{
_firstPacketLength = bytesRead + 2;
@@ -405,16 +439,7 @@ namespace Shadowsocks.Controller
_destEndPoint = SocketUtil.GetEndPoint(dst_addr, dst_port);
if (_command == 1)
{
byte[] response = {5, 0, 0, 1, 0, 0, 0, 0, 0, 0};
_connection.BeginSend(response, 0, response.Length, SocketFlags.None,
new AsyncCallback(ResponseCallback), null);
}
else if (_command == 3)
{
HandleUDPAssociate();
}
onSuccess.Invoke();
}
else
{
@@ -479,20 +504,6 @@ namespace Shadowsocks.Controller
}
}
private void ResponseCallback(IAsyncResult ar)
{
try
{
_connection.EndSend(ar);
StartConnect();
}
catch (Exception e)
{
Logging.LogUsefulException(e);
Close();
}
}
// inner class
private class ProxyTimer : Timer
{
@@ -716,6 +727,26 @@ namespace Shadowsocks.Controller
}
}
// private static readonly Random Rnd = new Random();
private void TryReadAvailableData()
{
int available = Math.Min(_connection.Available, RecvSize - _firstPacketLength);
if (available > 0)
{
// Pick a random chunk size, or is it truly necessary? Random packet size is some sort of 'characteristic' itself.
//lock (Rnd)
//{
// available = Rnd.Next(available + 1);
//}
var size = _connection.Receive(_connetionRecvBuffer, _firstPacketLength, available,
SocketFlags.None);
_firstPacketLength += size;
}
}
private void StartPipe(AsyncSession session)
{
if (_closed) return;
@@ -723,6 +754,9 @@ namespace Shadowsocks.Controller
{
_startReceivingTime = DateTime.Now;
session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeRemoteReceiveCallback), session);
TryReadAvailableData();
Logging.Debug($"_firstPacketLength = {_firstPacketLength}");
SendToServer(_firstPacketLength, session);
}
catch (Exception e)
@@ -24,7 +24,7 @@ namespace Shadowsocks.Controller
public string LatestVersionLocalName;
public event EventHandler CheckUpdateCompleted;
public const string Version = "3.4.2.1";
public const string Version = "3.4.3";
private class CheckUpdateTimer : System.Timers.Timer
{
+1
View File
@@ -33,6 +33,7 @@ Check for Updates at Startup=启动时检查更新
Check Pre-release Version=检查测试版更新
Edit Hotkeys...=编辑快捷键...
About...=关于...
Help=帮助
Quit=退出
Edit Servers=编辑服务器
Load Balance=负载均衡
+1
View File
@@ -33,6 +33,7 @@ Check for Updates at Startup=啟動時檢查更新
Check Pre-release Version=檢查發行前版本更新
Edit Hotkeys...=編輯快速鍵...
About...=關於...
Help=幫助
Quit=結束
Edit Servers=編輯伺服器
Load Balance=負載平衡
@@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Shadowsocks")]
[assembly: AssemblyCopyright("clowwindy and community 2016")]
[assembly: AssemblyCopyright("clowwindy & community 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
+14 -31
View File
@@ -25,43 +25,26 @@ namespace Shadowsocks.Util
public static class Utils
{
private static bool? _portableMode;
private static string TempPath = null;
public static bool IsPortableMode()
{
if (!_portableMode.HasValue)
{
_portableMode = File.Exists(Path.Combine(Application.StartupPath, "shadowsocks_portable_mode.txt"));
}
return _portableMode.Value;
}
private static string _tempPath = null;
// return path to store temporary files
public static string GetTempPath()
{
if (TempPath == null)
if (_tempPath == null)
{
if (IsPortableMode())
try
{
Directory.CreateDirectory(Path.Combine(Application.StartupPath, "temp"));
}
catch (Exception e)
{
TempPath = Path.GetTempPath();
Logging.LogUsefulException(e);
}
finally
{
// don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log
TempPath = Path.Combine(Application.StartupPath, "temp");
}
else
TempPath = Path.GetTempPath();
try
{
Directory.CreateDirectory(Path.Combine(Application.StartupPath, "ss_win_temp"));
// don't use "/", it will fail when we call explorer /select xxx/ss_win_temp\xxx.log
_tempPath = Path.Combine(Application.StartupPath, "ss_win_temp");
}
catch (Exception e)
{
Logging.Error(e);
throw;
}
}
return TempPath;
return _tempPath;
}
// return a full path with filename combined which pointed to the temporary directory
+17 -10
View File
@@ -197,11 +197,16 @@ namespace Shadowsocks.View
for (int y = 0; y < iconCopy.Height; y++)
{
Color color = originIcon.GetPixel(x, y);
if (color.A != 0 && color.R > 30)
if (color.A != 0)
{
if (!enabled)
{
iconCopy.SetPixel(x, y, Color.FromArgb((byte)(color.A / 1.25), color.R, color.G, color.B));
Color flyBlue = Color.FromArgb(192, 192, 192);
// Multiply with flyBlue
int red = color.R * flyBlue.R / 255;
int green = color.G * flyBlue.G / 255;
int blue = color.B * flyBlue.B / 255;
iconCopy.SetPixel(x, y, Color.FromArgb(color.A, red, green, blue));
}
else if (global)
{
@@ -282,16 +287,18 @@ namespace Shadowsocks.View
this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)),
this.ShareOverLANItem = CreateMenuItem("Allow Clients from LAN", new EventHandler(this.ShareOverLANItem_Click)),
new MenuItem("-"),
CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)),
this.VerboseLoggingToggleItem = CreateMenuItem( "Verbose Logging", new EventHandler(this.VerboseLoggingToggleItem_Click) ),
this.hotKeyItem = CreateMenuItem("Edit Hotkeys...", new EventHandler(this.hotKeyItem_Click)),
CreateMenuGroup("Updates...", new MenuItem[] {
CreateMenuItem("Check for Updates...", new EventHandler(this.checkUpdatesItem_Click)),
new MenuItem("-"),
this.autoCheckUpdatesToggleItem = CreateMenuItem("Check for Updates at Startup", new EventHandler(this.autoCheckUpdatesToggleItem_Click)),
this.checkPreReleaseToggleItem = CreateMenuItem("Check Pre-release Version", new EventHandler(this.checkPreReleaseToggleItem_Click)),
CreateMenuGroup("Help", new MenuItem[] {
CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)),
this.VerboseLoggingToggleItem = CreateMenuItem( "Verbose Logging", new EventHandler(this.VerboseLoggingToggleItem_Click) ),
CreateMenuGroup("Updates...", new MenuItem[] {
CreateMenuItem("Check for Updates...", new EventHandler(this.checkUpdatesItem_Click)),
new MenuItem("-"),
this.autoCheckUpdatesToggleItem = CreateMenuItem("Check for Updates at Startup", new EventHandler(this.autoCheckUpdatesToggleItem_Click)),
this.checkPreReleaseToggleItem = CreateMenuItem("Check Pre-release Version", new EventHandler(this.checkPreReleaseToggleItem_Click)),
}),
CreateMenuItem("About...", new EventHandler(this.AboutItem_Click)),
}),
CreateMenuItem("About...", new EventHandler(this.AboutItem_Click)),
new MenuItem("-"),
CreateMenuItem("Quit", new EventHandler(this.Quit_Click))
});