Browse Source

add load balancing

tags/2.5
clowwindy 9 years ago
parent
commit
4afd5faf3f
19 changed files with 234 additions and 41 deletions
  1. +0
    -0
      shadowsocks-csharp/Controller/Service/GfwListUpdater.cs
  2. +0
    -0
      shadowsocks-csharp/Controller/Service/Listener.cs
  3. +0
    -0
      shadowsocks-csharp/Controller/Service/PACServer.cs
  4. +0
    -0
      shadowsocks-csharp/Controller/Service/PolipoRunner.cs
  5. +0
    -0
      shadowsocks-csharp/Controller/Service/PortForwarder.cs
  6. +5
    -4
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  7. +5
    -4
      shadowsocks-csharp/Controller/Service/UDPRelay.cs
  8. +0
    -0
      shadowsocks-csharp/Controller/Service/UpdateChecker.cs
  9. +37
    -3
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  10. +72
    -0
      shadowsocks-csharp/Controller/Strategy/BalancingStrategy.cs
  11. +30
    -0
      shadowsocks-csharp/Controller/Strategy/IStrategy.cs
  12. +21
    -0
      shadowsocks-csharp/Controller/Strategy/StrategyManager.cs
  13. +0
    -0
      shadowsocks-csharp/Controller/System/AutoStartup.cs
  14. +0
    -0
      shadowsocks-csharp/Controller/System/SystemProxy.cs
  15. +1
    -0
      shadowsocks-csharp/Data/cn.txt
  16. +5
    -2
      shadowsocks-csharp/Model/Configuration.cs
  17. +1
    -1
      shadowsocks-csharp/View/ConfigForm.cs
  18. +44
    -17
      shadowsocks-csharp/View/MenuViewController.cs
  19. +13
    -10
      shadowsocks-csharp/shadowsocks-csharp.csproj

shadowsocks-csharp/Controller/GfwListUpdater.cs → shadowsocks-csharp/Controller/Service/GfwListUpdater.cs View File


shadowsocks-csharp/Controller/Listener.cs → shadowsocks-csharp/Controller/Service/Listener.cs View File


shadowsocks-csharp/Controller/PACServer.cs → shadowsocks-csharp/Controller/Service/PACServer.cs View File


shadowsocks-csharp/Controller/PolipoRunner.cs → shadowsocks-csharp/Controller/Service/PolipoRunner.cs View File


shadowsocks-csharp/Controller/PortForwarder.cs → shadowsocks-csharp/Controller/Service/PortForwarder.cs View File


shadowsocks-csharp/Controller/TCPRelay.cs → shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -5,16 +5,17 @@ using System.Net.Sockets;
using System.Net;
using Shadowsocks.Encryption;
using Shadowsocks.Model;
using Shadowsocks.Controller.Strategy;
namespace Shadowsocks.Controller
{
class TCPRelay : Listener.Service
{
private Configuration _config;
public TCPRelay(Configuration config)
private ShadowsocksController _controller;
public TCPRelay(ShadowsocksController controller)
{
this._config = config;
this._controller = controller;
}
public bool Handle(byte[] firstPacket, int length, Socket socket, object state)
@@ -30,7 +31,7 @@ namespace Shadowsocks.Controller
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
Handler handler = new Handler();
handler.connection = socket;
Server server = _config.GetCurrentServer();
Server server = _controller.GetCurrentStrategy().GetAServer(IStrategyCallerType.TCP, (IPEndPoint)socket.RemoteEndPoint);
handler.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password);
handler.server = server;

shadowsocks-csharp/Controller/UDPRelay.cs → shadowsocks-csharp/Controller/Service/UDPRelay.cs View File

@@ -6,16 +6,17 @@ using Shadowsocks.Model;
using System.Net.Sockets;
using System.Net;
using System.Runtime.CompilerServices;
using Shadowsocks.Controller.Strategy;
namespace Shadowsocks.Controller
{
class UDPRelay : Listener.Service
{
private Configuration _config;
private ShadowsocksController _controller;
private LRUCache<IPEndPoint, UDPHandler> _cache;
public UDPRelay(Configuration config)
public UDPRelay(ShadowsocksController controller)
{
this._config = config;
this._controller = controller;
this._cache = new LRUCache<IPEndPoint, UDPHandler>(512); // todo: choose a smart number
}
@@ -34,7 +35,7 @@ namespace Shadowsocks.Controller
UDPHandler handler = _cache.get(remoteEndPoint);
if (handler == null)
{
handler = new UDPHandler(socket, _config.GetCurrentServer(), remoteEndPoint);
handler = new UDPHandler(socket, _controller.GetCurrentStrategy().GetAServer(IStrategyCallerType.UDP, remoteEndPoint), remoteEndPoint);
_cache.add(remoteEndPoint, handler);
}
handler.Send(firstPacket, length);

shadowsocks-csharp/Controller/UpdateChecker.cs → shadowsocks-csharp/Controller/Service/UpdateChecker.cs View File


+ 37
- 3
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using Shadowsocks.Controller.Strategy;
namespace Shadowsocks.Controller
{
@@ -20,6 +21,7 @@ namespace Shadowsocks.Controller
private Listener _listener;
private PACServer _pacServer;
private Configuration _config;
private StrategyManager _strategyManager;
private PolipoRunner polipoRunner;
private GFWListUpdater gfwListUpdater;
private bool stopped = false;
@@ -49,6 +51,7 @@ namespace Shadowsocks.Controller
public ShadowsocksController()
{
_config = Configuration.Load();
_strategyManager = new StrategyManager(this);
}
public void Start()
@@ -70,11 +73,34 @@ namespace Shadowsocks.Controller
}
// always return copy
public Configuration GetConfiguration()
public Configuration GetConfigurationCopy()
{
return Configuration.Load();
}
// always return current instance
public Configuration GetCurrentConfiguration()
{
return _config;
}
public IList<IStrategy> GetStrategies()
{
return _strategyManager.GetStrategies();
}
public IStrategy GetCurrentStrategy()
{
foreach (var strategy in _strategyManager.GetStrategies())
{
if (strategy.ID == this._config.strategy)
{
return strategy;
}
}
return null;
}
public void SaveServers(List<Server> servers, int localPort)
{
_config.configs = servers;
@@ -134,6 +160,14 @@ namespace Shadowsocks.Controller
public void SelectServerIndex(int index)
{
_config.index = index;
_config.strategy = null;
SaveConfig(_config);
}
public void SelectStrategy(string strategyID)
{
_config.index = -1;
_config.strategy = strategyID;
SaveConfig(_config);
}
@@ -250,8 +284,8 @@ namespace Shadowsocks.Controller
{
polipoRunner.Start(_config);
TCPRelay tcpRelay = new TCPRelay(_config);
UDPRelay udpRelay = new UDPRelay(_config);
TCPRelay tcpRelay = new TCPRelay(this);
UDPRelay udpRelay = new UDPRelay(this);
List<Listener.Service> services = new List<Listener.Service>();
services.Add(tcpRelay);
services.Add(udpRelay);


+ 72
- 0
shadowsocks-csharp/Controller/Strategy/BalancingStrategy.cs View File

@@ -0,0 +1,72 @@
using Shadowsocks.Controller;
using Shadowsocks.Model;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
namespace Shadowsocks.Controller.Strategy
{
class BalancingStrategy : IStrategy
{
ShadowsocksController _controller;
Random _random;
public BalancingStrategy(ShadowsocksController controller)
{
_controller = controller;
_random = new Random();
}
public string Name
{
get
{
return "Load Balance";
}
}
public string ID
{
get
{
return "com.shadowsocks.strategy.balancing";
}
}
public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint)
{
var configs = _controller.GetCurrentConfiguration().configs;
int index;
if (type == IStrategyCallerType.TCP)
{
index = _random.Next();
}
else
{
index = localIPEndPoint.GetHashCode();
}
return configs[index % configs.Count];
}
public void UpdateLatency(Model.Server server)
{
// do nothing
}
public void UpdateLastRead(Model.Server server)
{
// do nothing
}
public void UpdateLastWrite(Model.Server server)
{
// do nothing
}
public void SetFailure(Model.Server server)
{
// do nothing
}
}
}

+ 30
- 0
shadowsocks-csharp/Controller/Strategy/IStrategy.cs View File

@@ -0,0 +1,30 @@
using Shadowsocks.Model;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
namespace Shadowsocks.Controller.Strategy
{
public enum IStrategyCallerType
{
TCP,
UDP
}
public interface IStrategy
{
string Name { get; }
string ID { get; }
Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint);
void UpdateLatency(Server server);
void UpdateLastRead(Server server);
void UpdateLastWrite(Server server);
void SetFailure(Server server);
}
}

+ 21
- 0
shadowsocks-csharp/Controller/Strategy/StrategyManager.cs View File

@@ -0,0 +1,21 @@
using Shadowsocks.Controller;
using System;
using System.Collections.Generic;
using System.Text;
namespace Shadowsocks.Controller.Strategy
{
class StrategyManager
{
List<IStrategy> _strategies;
public StrategyManager(ShadowsocksController controller)
{
_strategies = new List<IStrategy>();
_strategies.Add(new BalancingStrategy(controller));
}
public IList<IStrategy> GetStrategies()
{
return _strategies;
}
}
}

shadowsocks-csharp/Controller/AutoStartup.cs → shadowsocks-csharp/Controller/System/AutoStartup.cs View File


shadowsocks-csharp/Controller/SystemProxy.cs → shadowsocks-csharp/Controller/System/SystemProxy.cs View File


+ 1
- 0
shadowsocks-csharp/Data/cn.txt View File

@@ -23,6 +23,7 @@ Show Logs...=显示日志...
About...=关于...
Quit=退出
Edit Servers=编辑服务器
Load Balance=负载均衡

# Config Form



+ 5
- 2
shadowsocks-csharp/Model/Configuration.cs View File

@@ -11,6 +11,9 @@ namespace Shadowsocks.Model
public class Configuration
{
public List<Server> configs;
// when strategy is set, index is ignored
public string strategy;
public int index;
public bool global;
public bool enabled;
@@ -79,9 +82,9 @@ namespace Shadowsocks.Model
{
config.index = config.configs.Count - 1;
}
if (config.index < 0)
if (config.index < -1)
{
config.index = 0;
config.index = -1;
}
config.isDefault = false;
try


+ 1
- 1
shadowsocks-csharp/View/ConfigForm.cs View File

@@ -133,7 +133,7 @@ namespace Shadowsocks.View
private void LoadCurrentConfiguration()
{
_modifiedConfiguration = controller.GetConfiguration();
_modifiedConfiguration = controller.GetConfigurationCopy();
LoadConfiguration(_modifiedConfiguration);
_oldSelectedIndex = _modifiedConfiguration.index;
ServersListBox.SelectedIndex = _modifiedConfiguration.index;


+ 44
- 17
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -71,9 +71,9 @@ namespace Shadowsocks.View
LoadCurrentConfiguration();
updateChecker.CheckUpdate(controller.GetConfiguration());
updateChecker.CheckUpdate(controller.GetConfigurationCopy());
if (controller.GetConfiguration().isDefault)
if (controller.GetConfigurationCopy().isDefault)
{
_isFirstRun = true;
ShowConfigForm();
@@ -106,7 +106,7 @@ namespace Shadowsocks.View
{
icon = Resources.ss24;
}
Configuration config = controller.GetConfiguration();
Configuration config = controller.GetConfigurationCopy();
bool enabled = config.enabled;
bool global = config.global;
if (!enabled)
@@ -124,12 +124,21 @@ namespace Shadowsocks.View
}
_notifyIcon.Icon = Icon.FromHandle(icon.GetHicon());
string serverInfo = null;
if (config.strategy != null)
{
serverInfo = I18N.GetString(controller.GetCurrentStrategy().Name);
}
else
{
serverInfo = config.GetCurrentServer().FriendlyName();
}
// we want to show more details but notify icon title is limited to 63 characters
string text = I18N.GetString("Shadowsocks") + " " + UpdateChecker.Version + "\n" +
(enabled ?
I18N.GetString("System Proxy On: ") + (global ? I18N.GetString("Global") : I18N.GetString("PAC")) :
String.Format(I18N.GetString("Running: Port {0}"), config.localPort)) // this feedback is very important because they need to know Shadowsocks is running
+ "\n" + config.GetCurrentServer().FriendlyName();
+ "\n" + serverInfo;
_notifyIcon.Text = text.Substring(0, Math.Min(63, text.Length));
}
@@ -185,18 +194,18 @@ namespace Shadowsocks.View
private void controller_EnableStatusChanged(object sender, EventArgs e)
{
enableItem.Checked = controller.GetConfiguration().enabled;
enableItem.Checked = controller.GetConfigurationCopy().enabled;
modeItem.Enabled = enableItem.Checked;
}
void controller_ShareOverLANStatusChanged(object sender, EventArgs e)
{
ShareOverLANItem.Checked = controller.GetConfiguration().shareOverLan;
ShareOverLANItem.Checked = controller.GetConfigurationCopy().shareOverLan;
}
void controller_EnableGlobalChanged(object sender, EventArgs e)
{
globalModeItem.Checked = controller.GetConfiguration().global;
globalModeItem.Checked = controller.GetConfigurationCopy().global;
PACModeItem.Checked = !globalModeItem.Checked;
}
@@ -243,7 +252,7 @@ namespace Shadowsocks.View
private void LoadCurrentConfiguration()
{
Configuration config = controller.GetConfiguration();
Configuration config = controller.GetConfigurationCopy();
UpdateServersMenu();
enableItem.Checked = config.enabled;
modeItem.Enabled = config.enabled;
@@ -263,20 +272,32 @@ namespace Shadowsocks.View
{
items.RemoveAt(0);
}
Configuration configuration = controller.GetConfiguration();
for (int i = 0; i < configuration.configs.Count; i++)
int i = 0;
foreach (var strategy in controller.GetStrategies())
{
MenuItem item = new MenuItem(I18N.GetString(strategy.Name));
item.Tag = strategy.ID;
item.Click += AStrategyItem_Click;
items.Add(i, item);
i++;
}
Configuration configuration = controller.GetConfigurationCopy();
foreach (var server in configuration.configs)
{
Server server = configuration.configs[i];
MenuItem item = new MenuItem(server.FriendlyName());
item.Tag = i;
item.Click += AServerItem_Click;
items.Add(i, item);
i++;
}
if (configuration.index >= 0 && configuration.index < configuration.configs.Count)
foreach (MenuItem item in items)
{
items[configuration.index].Checked = true;
if (item.Tag != null && (item.Tag.ToString() == configuration.index.ToString() || item.Tag.ToString() == configuration.strategy))
{
item.Checked = true;
}
}
}
@@ -380,6 +401,12 @@ namespace Shadowsocks.View
controller.SelectServerIndex((int)item.Tag);
}
private void AStrategyItem_Click(object sender, EventArgs e)
{
MenuItem item = (MenuItem)sender;
controller.SelectStrategy((string)item.Tag);
}
private void ShowLogItem_Click(object sender, EventArgs e)
{
string argument = Logging.LogFile;
@@ -511,11 +538,11 @@ namespace Shadowsocks.View
{
if (!onlinePACItem.Checked)
{
if (String.IsNullOrEmpty(controller.GetConfiguration().pacUrl))
if (String.IsNullOrEmpty(controller.GetConfigurationCopy().pacUrl))
{
UpdateOnlinePACURLItem_Click(sender, e);
}
if (!String.IsNullOrEmpty(controller.GetConfiguration().pacUrl))
if (!String.IsNullOrEmpty(controller.GetConfigurationCopy().pacUrl))
{
localPACItem.Checked = false;
onlinePACItem.Checked = true;
@@ -527,7 +554,7 @@ namespace Shadowsocks.View
private void UpdateOnlinePACURLItem_Click(object sender, EventArgs e)
{
string origPacUrl = controller.GetConfiguration().pacUrl;
string origPacUrl = controller.GetConfigurationCopy().pacUrl;
string pacUrl = Microsoft.VisualBasic.Interaction.InputBox(
I18N.GetString("Please input PAC Url"),
I18N.GetString("Edit Online PAC URL"),


+ 13
- 10
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -124,15 +124,15 @@
<Compile Include="3rd\zxing\ResultPoint.cs" />
<Compile Include="3rd\zxing\ResultPointCallback.cs" />
<Compile Include="3rd\zxing\WriterException.cs" />
<Compile Include="Controller\AutoStartup.cs" />
<Compile Include="Controller\System\AutoStartup.cs" />
<Compile Include="Controller\FileManager.cs" />
<Compile Include="Controller\GFWListUpdater.cs" />
<Compile Include="Controller\Service\GFWListUpdater.cs" />
<Compile Include="Controller\I18N.cs" />
<Compile Include="Controller\Listener.cs" />
<Compile Include="Controller\Service\Listener.cs" />
<Compile Include="Controller\Logging.cs" />
<Compile Include="Controller\PortForwarder.cs" />
<Compile Include="Controller\UDPRelay.cs" />
<Compile Include="Controller\UpdateChecker.cs" />
<Compile Include="Controller\Service\PortForwarder.cs" />
<Compile Include="Controller\Service\UDPRelay.cs" />
<Compile Include="Controller\Service\UpdateChecker.cs" />
<Compile Include="Encryption\EncryptorBase.cs" />
<Compile Include="Encryption\EncryptorFactory.cs" />
<Compile Include="Encryption\IVEncryptor.cs" />
@@ -142,7 +142,7 @@
<Compile Include="Encryption\SodiumEncryptor.cs" />
<Compile Include="Encryption\TableEncryptor.cs" />
<Compile Include="Encryption\IEncryptor.cs" />
<Compile Include="Controller\PACServer.cs" />
<Compile Include="Controller\Service\PACServer.cs" />
<Compile Include="Model\Server.cs" />
<Compile Include="Model\Configuration.cs" />
<Compile Include="Properties\Resources.Designer.cs">
@@ -150,6 +150,9 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Controller\Strategy\BalancingStrategy.cs" />
<Compile Include="Controller\Strategy\StrategyManager.cs" />
<Compile Include="Controller\Strategy\IStrategy.cs" />
<Compile Include="Util\Util.cs" />
<Compile Include="View\ConfigForm.cs">
<SubType>Form</SubType>
@@ -157,12 +160,12 @@
<Compile Include="View\ConfigForm.Designer.cs">
<DependentUpon>ConfigForm.cs</DependentUpon>
</Compile>
<Compile Include="Controller\TCPRelay.cs" />
<Compile Include="Controller\PolipoRunner.cs" />
<Compile Include="Controller\Service\TCPRelay.cs" />
<Compile Include="Controller\Service\PolipoRunner.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Controller\ShadowsocksController.cs" />
<Compile Include="Controller\SystemProxy.cs" />
<Compile Include="Controller\System\SystemProxy.cs" />
<Compile Include="View\MenuViewController.cs" />
<Compile Include="View\QRCodeForm.cs">
<SubType>Form</SubType>


Loading…
Cancel
Save