Compare commits

...
6 Commits
Author SHA1 Message Date
Syrone Wong 60a5572808 update CHANGES and bump version 2017-04-08 19:22:11 +08:00
Syrone Wong 877644609b spare enough space for UDP packet 2017-04-08 18:59:39 +08:00
Syrone Wong 54335d4889 capture non-whitespace chars for ss url tag 2017-04-08 18:56:30 +08:00
Syrone Wong 08f12b3b24 reduce port forwarder buffer size 2017-04-05 18:55:44 +08:00
Syrone Wong 1c8f4168cf do not popup if we have fake Base64 strings 2017-04-05 18:42:52 +08:00
Syrone Wong 43672a8bda allow to add multiple servers via ss url
invalid URLs will be ignored
2017-04-05 18:14:58 +08:00
8 changed files with 74 additions and 53 deletions
+5
View File
@@ -1,3 +1,8 @@
4.0.1 2017-04-08
- Fix UDP relay
- Allow to add multiple servers via Shadowsocks URL
- Bug fixes and improvements
4.0 2017-04-04
- Add AEAD ciphers support, removed OTA
- I18N: add Japanese support, update Traditional Chinese strings
@@ -7,11 +7,11 @@ namespace Shadowsocks.Controller
{
class PortForwarder : Listener.Service
{
int _targetPort;
private readonly int _targetPort;
public PortForwarder(int targetPort)
{
this._targetPort = targetPort;
_targetPort = targetPort;
}
public override bool Handle(byte[] firstPacket, int length, Socket socket, object state)
@@ -20,11 +20,11 @@ namespace Shadowsocks.Controller
{
return false;
}
new Handler().Start(firstPacket, length, socket, this._targetPort);
new Handler().Start(firstPacket, length, socket, _targetPort);
return true;
}
class Handler
private class Handler
{
private byte[] _firstPacket;
private int _firstPacketLength;
@@ -33,7 +33,7 @@ namespace Shadowsocks.Controller
private bool _closed = false;
private bool _localShutdown = false;
private bool _remoteShutdown = false;
public const int RecvSize = 16384;
private const int RecvSize = 2048;
// remote receive buffer
private byte[] remoteRecvBuffer = new byte[RecvSize];
// connection receive buffer
@@ -44,9 +44,9 @@ namespace Shadowsocks.Controller
public void Start(byte[] firstPacket, int length, Socket socket, int targetPort)
{
this._firstPacket = firstPacket;
this._firstPacketLength = length;
this._local = socket;
_firstPacket = firstPacket;
_firstPacketLength = length;
_local = socket;
try
{
EndPoint remoteEP = SocketUtil.GetEndPoint("127.0.0.1", targetPort);
@@ -58,7 +58,7 @@ namespace Shadowsocks.Controller
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
Close();
}
}
@@ -77,7 +77,7 @@ namespace Shadowsocks.Controller
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
Close();
}
}
@@ -89,12 +89,12 @@ namespace Shadowsocks.Controller
}
try
{
_remote.BeginSend(_firstPacket, 0, _firstPacketLength, 0, new AsyncCallback(StartPipe), null);
_remote.BeginSend(_firstPacket, 0, _firstPacketLength, 0, StartPipe, null);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
Close();
}
}
@@ -108,14 +108,14 @@ namespace Shadowsocks.Controller
{
_remote.EndSend(ar);
_remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(PipeRemoteReceiveCallback), null);
PipeRemoteReceiveCallback, null);
_local.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(PipeConnectionReceiveCallback), null);
PipeConnectionReceiveCallback, null);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
Close();
}
}
@@ -128,10 +128,9 @@ namespace Shadowsocks.Controller
try
{
int bytesRead = _remote.EndReceive(ar);
if (bytesRead > 0)
{
_local.BeginSend(remoteRecvBuffer, 0, bytesRead, 0, new AsyncCallback(PipeConnectionSendCallback), null);
_local.BeginSend(remoteRecvBuffer, 0, bytesRead, 0, PipeConnectionSendCallback, null);
}
else
{
@@ -143,7 +142,7 @@ namespace Shadowsocks.Controller
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
Close();
}
}
@@ -156,10 +155,9 @@ namespace Shadowsocks.Controller
try
{
int bytesRead = _local.EndReceive(ar);
if (bytesRead > 0)
{
_remote.BeginSend(connetionRecvBuffer, 0, bytesRead, 0, new AsyncCallback(PipeRemoteSendCallback), null);
_remote.BeginSend(connetionRecvBuffer, 0, bytesRead, 0, PipeRemoteSendCallback, null);
}
else
{
@@ -171,7 +169,7 @@ namespace Shadowsocks.Controller
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
Close();
}
}
@@ -184,13 +182,13 @@ namespace Shadowsocks.Controller
try
{
_remote.EndSend(ar);
_local.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(PipeConnectionReceiveCallback), null);
_local.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
PipeConnectionReceiveCallback, null);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
Close();
}
}
@@ -203,13 +201,13 @@ namespace Shadowsocks.Controller
try
{
_local.EndSend(ar);
_remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(PipeRemoteReceiveCallback), null);
_remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0,
PipeRemoteReceiveCallback, null);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
Close();
}
}
@@ -217,7 +215,7 @@ namespace Shadowsocks.Controller
{
if (_localShutdown && _remoteShutdown)
{
this.Close();
Close();
}
}
@@ -53,7 +53,7 @@ namespace Shadowsocks.Controller
private Socket _remote;
private Server _server;
private byte[] _buffer = new byte[1500];
private byte[] _buffer = new byte[65536];
private IPEndPoint _localEndPoint;
private IPEndPoint _remoteEndPoint;
@@ -81,7 +81,7 @@ namespace Shadowsocks.Controller
IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password);
byte[] dataIn = new byte[length - 3];
Array.Copy(data, 3, dataIn, 0, length - 3);
byte[] dataOut = new byte[length - 3 + 16];
byte[] dataOut = new byte[65536]; // enough space for AEAD ciphers
int outlen;
encryptor.EncryptUDP(dataIn, length - 3, dataOut, out outlen);
Logging.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay");
@@ -24,7 +24,7 @@ namespace Shadowsocks.Controller
public string LatestVersionLocalName;
public event EventHandler CheckUpdateCompleted;
public const string Version = "4.0";
public const string Version = "4.0.1";
private class CheckUpdateTimer : System.Timers.Timer
{
@@ -163,8 +163,13 @@ namespace Shadowsocks.Controller
{
try
{
var server = new Server(ssURL);
_config.configs.Add(server);
if (ssURL.IsNullOrEmpty() || ssURL.IsWhiteSpace()) return false;
var servers = Server.GetServers(ssURL);
if (servers == null || servers.Count == 0) return false;
foreach (var server in servers)
{
_config.configs.Add(server);
}
_config.index = _config.configs.Count - 1;
SaveConfig(_config);
return true;
@@ -18,7 +18,7 @@ namespace Shadowsocks.Encryption.AEAD
private static readonly byte[] InfoBytes = Encoding.ASCII.GetBytes(Info);
// for UDP only
protected static byte[] _udpTmpBuf = new byte[MAX_INPUT_SIZE];
protected static byte[] _udpTmpBuf = new byte[65536];
// every connection should create its own buffer
private CircularBuffer<byte> _encCircularBuffer = new CircularBuffer<byte>(MAX_INPUT_SIZE * 2, false);
@@ -11,7 +11,7 @@ namespace Shadowsocks.Encryption.Stream
: EncryptorBase
{
// for UDP only
protected static byte[] _udpTmpBuf = new byte[MAX_INPUT_SIZE];
protected static byte[] _udpTmpBuf = new byte[65536];
// every connection should create its own buffer
private CircularBuffer<byte> _encCircularBuffer = new CircularBuffer<byte>(TCPHandler.BufferSize * 2, false);
+31 -18
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
@@ -10,9 +11,8 @@ namespace Shadowsocks.Model
public class Server
{
public static readonly Regex
UrlFinder = new Regex("^(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?$", RegexOptions.IgnoreCase),
DetailsParser = new Regex("^((?<method>.+?):(?<password>.*)@(?<hostname>.+?)" +
":(?<port>\\d+?))$", RegexOptions.IgnoreCase);
UrlFinder = new Regex(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase),
DetailsParser = new Regex(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase);
private const int DefaultServerTimeoutSec = 5;
public const int MaxServerTimeoutSec = 20;
@@ -43,9 +43,10 @@ namespace Shadowsocks.Model
}
string serverStr;
// CheckHostName() won't do a real DNS lookup
var hostType = Uri.CheckHostName( server );
var hostType = Uri.CheckHostName(server);
switch ( hostType ) {
switch (hostType)
{
case UriHostNameType.IPv6:
serverStr = $"[{server}]:{server_port}";
break;
@@ -69,20 +70,32 @@ namespace Shadowsocks.Model
timeout = DefaultServerTimeoutSec;
}
public Server(string ssURL) : this()
public static List<Server> GetServers(string ssURL)
{
var match = UrlFinder.Match(ssURL);
if (!match.Success) throw new FormatException();
var base64 = match.Groups[1].Value;
var tag = match.Groups[3].Value;
if (!tag.IsNullOrEmpty())
remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
match = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
method = match.Groups["method"].Value;
password = match.Groups["password"].Value;
server = match.Groups["hostname"].Value;
server_port = int.Parse(match.Groups["port"].Value);
var matches = UrlFinder.Matches(ssURL);
if (matches.Count <= 0) return null;
List<Server> servers = new List<Server>();
foreach (Match match in matches)
{
Server tmp = new Server();
var base64 = match.Groups["base64"].Value;
var tag = match.Groups["tag"].Value;
if (!tag.IsNullOrEmpty())
{
tmp.remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
}
Match details = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
if (!details.Success)
continue;
tmp.method = details.Groups["method"].Value;
tmp.password = details.Groups["password"].Value;
tmp.server = details.Groups["hostname"].Value;
tmp.server_port = int.Parse(details.Groups["port"].Value);
servers.Add(tmp);
}
return servers;
}
public string Identifier()