@@ -5,16 +5,17 @@ using System.Net.Sockets; | |||||
using System.Net; | using System.Net; | ||||
using Shadowsocks.Encryption; | using Shadowsocks.Encryption; | ||||
using Shadowsocks.Model; | using Shadowsocks.Model; | ||||
using Shadowsocks.Controller.Strategy; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
class TCPRelay : Listener.Service | 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) | 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); | socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | ||||
Handler handler = new Handler(); | Handler handler = new Handler(); | ||||
handler.connection = socket; | 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.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password); | ||||
handler.server = server; | handler.server = server; | ||||
@@ -6,16 +6,17 @@ using Shadowsocks.Model; | |||||
using System.Net.Sockets; | using System.Net.Sockets; | ||||
using System.Net; | using System.Net; | ||||
using System.Runtime.CompilerServices; | using System.Runtime.CompilerServices; | ||||
using Shadowsocks.Controller.Strategy; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
class UDPRelay : Listener.Service | class UDPRelay : Listener.Service | ||||
{ | { | ||||
private Configuration _config; | |||||
private ShadowsocksController _controller; | |||||
private LRUCache<IPEndPoint, UDPHandler> _cache; | 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 | this._cache = new LRUCache<IPEndPoint, UDPHandler>(512); // todo: choose a smart number | ||||
} | } | ||||
@@ -34,7 +35,7 @@ namespace Shadowsocks.Controller | |||||
UDPHandler handler = _cache.get(remoteEndPoint); | UDPHandler handler = _cache.get(remoteEndPoint); | ||||
if (handler == null) | 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); | _cache.add(remoteEndPoint, handler); | ||||
} | } | ||||
handler.Send(firstPacket, length); | handler.Send(firstPacket, length); |
@@ -5,6 +5,7 @@ using System.Collections.Generic; | |||||
using System.Text; | using System.Text; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Net.Sockets; | using System.Net.Sockets; | ||||
using Shadowsocks.Controller.Strategy; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
@@ -20,6 +21,7 @@ namespace Shadowsocks.Controller | |||||
private Listener _listener; | private Listener _listener; | ||||
private PACServer _pacServer; | private PACServer _pacServer; | ||||
private Configuration _config; | private Configuration _config; | ||||
private StrategyManager _strategyManager; | |||||
private PolipoRunner polipoRunner; | private PolipoRunner polipoRunner; | ||||
private GFWListUpdater gfwListUpdater; | private GFWListUpdater gfwListUpdater; | ||||
private bool stopped = false; | private bool stopped = false; | ||||
@@ -49,6 +51,7 @@ namespace Shadowsocks.Controller | |||||
public ShadowsocksController() | public ShadowsocksController() | ||||
{ | { | ||||
_config = Configuration.Load(); | _config = Configuration.Load(); | ||||
_strategyManager = new StrategyManager(this); | |||||
} | } | ||||
public void Start() | public void Start() | ||||
@@ -70,11 +73,34 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
// always return copy | // always return copy | ||||
public Configuration GetConfiguration() | |||||
public Configuration GetConfigurationCopy() | |||||
{ | { | ||||
return Configuration.Load(); | 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) | public void SaveServers(List<Server> servers, int localPort) | ||||
{ | { | ||||
_config.configs = servers; | _config.configs = servers; | ||||
@@ -134,6 +160,14 @@ namespace Shadowsocks.Controller | |||||
public void SelectServerIndex(int index) | public void SelectServerIndex(int index) | ||||
{ | { | ||||
_config.index = index; | _config.index = index; | ||||
_config.strategy = null; | |||||
SaveConfig(_config); | |||||
} | |||||
public void SelectStrategy(string strategyID) | |||||
{ | |||||
_config.index = -1; | |||||
_config.strategy = strategyID; | |||||
SaveConfig(_config); | SaveConfig(_config); | ||||
} | } | ||||
@@ -250,8 +284,8 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
polipoRunner.Start(_config); | 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>(); | List<Listener.Service> services = new List<Listener.Service>(); | ||||
services.Add(tcpRelay); | services.Add(tcpRelay); | ||||
services.Add(udpRelay); | services.Add(udpRelay); | ||||
@@ -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 | |||||
} | |||||
} | |||||
} |
@@ -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); | |||||
} | |||||
} |
@@ -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; | |||||
} | |||||
} | |||||
} |
@@ -23,6 +23,7 @@ Show Logs...=显示日志... | |||||
About...=关于... | About...=关于... | ||||
Quit=退出 | Quit=退出 | ||||
Edit Servers=编辑服务器 | Edit Servers=编辑服务器 | ||||
Load Balance=负载均衡 | |||||
# Config Form | # Config Form | ||||
@@ -11,6 +11,9 @@ namespace Shadowsocks.Model | |||||
public class Configuration | public class Configuration | ||||
{ | { | ||||
public List<Server> configs; | public List<Server> configs; | ||||
// when strategy is set, index is ignored | |||||
public string strategy; | |||||
public int index; | public int index; | ||||
public bool global; | public bool global; | ||||
public bool enabled; | public bool enabled; | ||||
@@ -79,9 +82,9 @@ namespace Shadowsocks.Model | |||||
{ | { | ||||
config.index = config.configs.Count - 1; | config.index = config.configs.Count - 1; | ||||
} | } | ||||
if (config.index < 0) | |||||
if (config.index < -1) | |||||
{ | { | ||||
config.index = 0; | |||||
config.index = -1; | |||||
} | } | ||||
config.isDefault = false; | config.isDefault = false; | ||||
try | try | ||||
@@ -133,7 +133,7 @@ namespace Shadowsocks.View | |||||
private void LoadCurrentConfiguration() | private void LoadCurrentConfiguration() | ||||
{ | { | ||||
_modifiedConfiguration = controller.GetConfiguration(); | |||||
_modifiedConfiguration = controller.GetConfigurationCopy(); | |||||
LoadConfiguration(_modifiedConfiguration); | LoadConfiguration(_modifiedConfiguration); | ||||
_oldSelectedIndex = _modifiedConfiguration.index; | _oldSelectedIndex = _modifiedConfiguration.index; | ||||
ServersListBox.SelectedIndex = _modifiedConfiguration.index; | ServersListBox.SelectedIndex = _modifiedConfiguration.index; | ||||
@@ -71,9 +71,9 @@ namespace Shadowsocks.View | |||||
LoadCurrentConfiguration(); | LoadCurrentConfiguration(); | ||||
updateChecker.CheckUpdate(controller.GetConfiguration()); | |||||
updateChecker.CheckUpdate(controller.GetConfigurationCopy()); | |||||
if (controller.GetConfiguration().isDefault) | |||||
if (controller.GetConfigurationCopy().isDefault) | |||||
{ | { | ||||
_isFirstRun = true; | _isFirstRun = true; | ||||
ShowConfigForm(); | ShowConfigForm(); | ||||
@@ -106,7 +106,7 @@ namespace Shadowsocks.View | |||||
{ | { | ||||
icon = Resources.ss24; | icon = Resources.ss24; | ||||
} | } | ||||
Configuration config = controller.GetConfiguration(); | |||||
Configuration config = controller.GetConfigurationCopy(); | |||||
bool enabled = config.enabled; | bool enabled = config.enabled; | ||||
bool global = config.global; | bool global = config.global; | ||||
if (!enabled) | if (!enabled) | ||||
@@ -124,12 +124,21 @@ namespace Shadowsocks.View | |||||
} | } | ||||
_notifyIcon.Icon = Icon.FromHandle(icon.GetHicon()); | _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 | // we want to show more details but notify icon title is limited to 63 characters | ||||
string text = I18N.GetString("Shadowsocks") + " " + UpdateChecker.Version + "\n" + | string text = I18N.GetString("Shadowsocks") + " " + UpdateChecker.Version + "\n" + | ||||
(enabled ? | (enabled ? | ||||
I18N.GetString("System Proxy On: ") + (global ? I18N.GetString("Global") : I18N.GetString("PAC")) : | 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 | 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)); | _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) | private void controller_EnableStatusChanged(object sender, EventArgs e) | ||||
{ | { | ||||
enableItem.Checked = controller.GetConfiguration().enabled; | |||||
enableItem.Checked = controller.GetConfigurationCopy().enabled; | |||||
modeItem.Enabled = enableItem.Checked; | modeItem.Enabled = enableItem.Checked; | ||||
} | } | ||||
void controller_ShareOverLANStatusChanged(object sender, EventArgs e) | void controller_ShareOverLANStatusChanged(object sender, EventArgs e) | ||||
{ | { | ||||
ShareOverLANItem.Checked = controller.GetConfiguration().shareOverLan; | |||||
ShareOverLANItem.Checked = controller.GetConfigurationCopy().shareOverLan; | |||||
} | } | ||||
void controller_EnableGlobalChanged(object sender, EventArgs e) | void controller_EnableGlobalChanged(object sender, EventArgs e) | ||||
{ | { | ||||
globalModeItem.Checked = controller.GetConfiguration().global; | |||||
globalModeItem.Checked = controller.GetConfigurationCopy().global; | |||||
PACModeItem.Checked = !globalModeItem.Checked; | PACModeItem.Checked = !globalModeItem.Checked; | ||||
} | } | ||||
@@ -243,7 +252,7 @@ namespace Shadowsocks.View | |||||
private void LoadCurrentConfiguration() | private void LoadCurrentConfiguration() | ||||
{ | { | ||||
Configuration config = controller.GetConfiguration(); | |||||
Configuration config = controller.GetConfigurationCopy(); | |||||
UpdateServersMenu(); | UpdateServersMenu(); | ||||
enableItem.Checked = config.enabled; | enableItem.Checked = config.enabled; | ||||
modeItem.Enabled = config.enabled; | modeItem.Enabled = config.enabled; | ||||
@@ -263,20 +272,32 @@ namespace Shadowsocks.View | |||||
{ | { | ||||
items.RemoveAt(0); | 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()); | MenuItem item = new MenuItem(server.FriendlyName()); | ||||
item.Tag = i; | item.Tag = i; | ||||
item.Click += AServerItem_Click; | item.Click += AServerItem_Click; | ||||
items.Add(i, item); | 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); | 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) | private void ShowLogItem_Click(object sender, EventArgs e) | ||||
{ | { | ||||
string argument = Logging.LogFile; | string argument = Logging.LogFile; | ||||
@@ -511,11 +538,11 @@ namespace Shadowsocks.View | |||||
{ | { | ||||
if (!onlinePACItem.Checked) | if (!onlinePACItem.Checked) | ||||
{ | { | ||||
if (String.IsNullOrEmpty(controller.GetConfiguration().pacUrl)) | |||||
if (String.IsNullOrEmpty(controller.GetConfigurationCopy().pacUrl)) | |||||
{ | { | ||||
UpdateOnlinePACURLItem_Click(sender, e); | UpdateOnlinePACURLItem_Click(sender, e); | ||||
} | } | ||||
if (!String.IsNullOrEmpty(controller.GetConfiguration().pacUrl)) | |||||
if (!String.IsNullOrEmpty(controller.GetConfigurationCopy().pacUrl)) | |||||
{ | { | ||||
localPACItem.Checked = false; | localPACItem.Checked = false; | ||||
onlinePACItem.Checked = true; | onlinePACItem.Checked = true; | ||||
@@ -527,7 +554,7 @@ namespace Shadowsocks.View | |||||
private void UpdateOnlinePACURLItem_Click(object sender, EventArgs e) | private void UpdateOnlinePACURLItem_Click(object sender, EventArgs e) | ||||
{ | { | ||||
string origPacUrl = controller.GetConfiguration().pacUrl; | |||||
string origPacUrl = controller.GetConfigurationCopy().pacUrl; | |||||
string pacUrl = Microsoft.VisualBasic.Interaction.InputBox( | string pacUrl = Microsoft.VisualBasic.Interaction.InputBox( | ||||
I18N.GetString("Please input PAC Url"), | I18N.GetString("Please input PAC Url"), | ||||
I18N.GetString("Edit Online PAC URL"), | I18N.GetString("Edit Online PAC URL"), | ||||
@@ -124,15 +124,15 @@ | |||||
<Compile Include="3rd\zxing\ResultPoint.cs" /> | <Compile Include="3rd\zxing\ResultPoint.cs" /> | ||||
<Compile Include="3rd\zxing\ResultPointCallback.cs" /> | <Compile Include="3rd\zxing\ResultPointCallback.cs" /> | ||||
<Compile Include="3rd\zxing\WriterException.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\FileManager.cs" /> | ||||
<Compile Include="Controller\GFWListUpdater.cs" /> | |||||
<Compile Include="Controller\Service\GFWListUpdater.cs" /> | |||||
<Compile Include="Controller\I18N.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\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\EncryptorBase.cs" /> | ||||
<Compile Include="Encryption\EncryptorFactory.cs" /> | <Compile Include="Encryption\EncryptorFactory.cs" /> | ||||
<Compile Include="Encryption\IVEncryptor.cs" /> | <Compile Include="Encryption\IVEncryptor.cs" /> | ||||
@@ -142,7 +142,7 @@ | |||||
<Compile Include="Encryption\SodiumEncryptor.cs" /> | <Compile Include="Encryption\SodiumEncryptor.cs" /> | ||||
<Compile Include="Encryption\TableEncryptor.cs" /> | <Compile Include="Encryption\TableEncryptor.cs" /> | ||||
<Compile Include="Encryption\IEncryptor.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\Server.cs" /> | ||||
<Compile Include="Model\Configuration.cs" /> | <Compile Include="Model\Configuration.cs" /> | ||||
<Compile Include="Properties\Resources.Designer.cs"> | <Compile Include="Properties\Resources.Designer.cs"> | ||||
@@ -150,6 +150,9 @@ | |||||
<DesignTime>True</DesignTime> | <DesignTime>True</DesignTime> | ||||
<DependentUpon>Resources.resx</DependentUpon> | <DependentUpon>Resources.resx</DependentUpon> | ||||
</Compile> | </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="Util\Util.cs" /> | ||||
<Compile Include="View\ConfigForm.cs"> | <Compile Include="View\ConfigForm.cs"> | ||||
<SubType>Form</SubType> | <SubType>Form</SubType> | ||||
@@ -157,12 +160,12 @@ | |||||
<Compile Include="View\ConfigForm.Designer.cs"> | <Compile Include="View\ConfigForm.Designer.cs"> | ||||
<DependentUpon>ConfigForm.cs</DependentUpon> | <DependentUpon>ConfigForm.cs</DependentUpon> | ||||
</Compile> | </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="Program.cs" /> | ||||
<Compile Include="Properties\AssemblyInfo.cs" /> | <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
<Compile Include="Controller\ShadowsocksController.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\MenuViewController.cs" /> | ||||
<Compile Include="View\QRCodeForm.cs"> | <Compile Include="View\QRCodeForm.cs"> | ||||
<SubType>Form</SubType> | <SubType>Form</SubType> | ||||