Browse Source

add connect timeout

tags/2.5
clowwindy 9 years ago
parent
commit
449df1022d
3 changed files with 70 additions and 15 deletions
  1. +3
    -0
      shadowsocks-csharp/Controller/Logging.cs
  2. +63
    -13
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  3. +4
    -2
      shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs

+ 3
- 0
shadowsocks-csharp/Controller/Logging.cs View File

@@ -63,6 +63,9 @@ namespace Shadowsocks.Controller
Console.WriteLine(e); Console.WriteLine(e);
} }
} }
else if (e is ObjectDisposedException)
{
}
else else
{ {
Console.WriteLine(e); Console.WriteLine(e);


+ 63
- 13
shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -6,6 +6,7 @@ using System.Net;
using Shadowsocks.Encryption; using Shadowsocks.Encryption;
using Shadowsocks.Model; using Shadowsocks.Model;
using Shadowsocks.Controller.Strategy; using Shadowsocks.Controller.Strategy;
using System.Timers;
namespace Shadowsocks.Controller namespace Shadowsocks.Controller
{ {
@@ -48,6 +49,7 @@ namespace Shadowsocks.Controller
public Socket connection; public Socket connection;
public ShadowsocksController controller; public ShadowsocksController controller;
private int retryCount = 0; private int retryCount = 0;
private bool connected;
private byte command; private byte command;
private byte[] _firstPacket; private byte[] _firstPacket;
@@ -129,7 +131,7 @@ namespace Shadowsocks.Controller
remote.Shutdown(SocketShutdown.Both); remote.Shutdown(SocketShutdown.Both);
remote.Close(); remote.Close();
} }
catch (SocketException e)
catch (Exception e)
{ {
Logging.LogUsefulException(e); Logging.LogUsefulException(e);
} }
@@ -315,6 +317,15 @@ namespace Shadowsocks.Controller
} }
} }
private class ServerTimer : Timer
{
public Server Server;
public ServerTimer(int p) :base(p)
{
}
}
private void StartConnect() private void StartConnect()
{ {
try try
@@ -337,10 +348,16 @@ namespace Shadowsocks.Controller
remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
_startConnectTime = DateTime.Now; _startConnectTime = DateTime.Now;
ServerTimer connectTimer = new ServerTimer(3000);
connectTimer.AutoReset = false;
connectTimer.Elapsed += connectTimer_Elapsed;
connectTimer.Enabled = true;
connectTimer.Server = server;
connected = false;
// Connect to the remote endpoint. // Connect to the remote endpoint.
remote.BeginConnect(remoteEP, remote.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), null);
new AsyncCallback(ConnectCallback), connectTimer);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -349,39 +366,72 @@ namespace Shadowsocks.Controller
} }
} }
private void connectTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (connected)
{
return;
}
Server server = ((ServerTimer)sender).Server;
controller.GetCurrentStrategy().SetFailure(server);
Console.WriteLine(String.Format("{0} timed out", server.FriendlyName()));
remote.Close();
RetryConnect();
}
private void RetryConnect()
{
if (retryCount < 4)
{
Console.WriteLine("Connection failed, retrying");
StartConnect();
retryCount++;
}
else
{
this.Close();
}
}
private void ConnectCallback(IAsyncResult ar) private void ConnectCallback(IAsyncResult ar)
{ {
Server server = null;
if (closed) if (closed)
{ {
return; return;
} }
try try
{ {
ServerTimer timer = (ServerTimer)ar.AsyncState;
server = timer.Server;
timer.Elapsed -= connectTimer_Elapsed;
timer.Enabled = false;
timer.Dispose();
// Complete the connection. // Complete the connection.
remote.EndConnect(ar); remote.EndConnect(ar);
connected = true;
//Console.WriteLine("Socket connected to {0}", //Console.WriteLine("Socket connected to {0}",
// remote.RemoteEndPoint.ToString()); // remote.RemoteEndPoint.ToString());
var latency = DateTime.Now - _startConnectTime; var latency = DateTime.Now - _startConnectTime;
controller.GetCurrentStrategy().UpdateLatency(this.server, latency);
controller.GetCurrentStrategy().UpdateLatency(server, latency);
StartPipe(); StartPipe();
} }
catch (ArgumentException e)
{
}
catch (Exception e) catch (Exception e)
{ {
controller.GetCurrentStrategy().SetFailure(this.server);
Logging.LogUsefulException(e);
if (retryCount < 3)
{
Console.WriteLine("Connection failed, retrying");
StartConnect();
retryCount++;
}
else
if (server != null)
{ {
this.Close();
controller.GetCurrentStrategy().SetFailure(server);
} }
Logging.LogUsefulException(e);
RetryConnect();
} }
} }


+ 4
- 2
shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs View File

@@ -75,8 +75,10 @@ namespace Shadowsocks.Controller.Strategy
public Server GetAServer(IStrategyCallerType type, System.Net.IPEndPoint localIPEndPoint) public Server GetAServer(IStrategyCallerType type, System.Net.IPEndPoint localIPEndPoint)
{ {
// TODO don't choose new server too frequently
ChooseNewServer();
if (type == IStrategyCallerType.TCP)
{
ChooseNewServer();
}
return _currentServer; return _currentServer;
} }


Loading…
Cancel
Save