diff --git a/shadowsocks-csharp/Controller/Service/PortForwarder.cs b/shadowsocks-csharp/Controller/Service/PortForwarder.cs
index 4f78a24c..f76a1284 100644
--- a/shadowsocks-csharp/Controller/Service/PortForwarder.cs
+++ b/shadowsocks-csharp/Controller/Service/PortForwarder.cs
@@ -1,6 +1,7 @@
using System;
using System.Net;
using System.Net.Sockets;
+using Shadowsocks.Util;
namespace Shadowsocks.Controller
{
@@ -45,14 +46,9 @@ namespace Shadowsocks.Controller
this._local = socket;
try
{
- // TODO async resolving
- IPAddress ipAddress;
- bool parsed = IPAddress.TryParse("127.0.0.1", out ipAddress);
- IPEndPoint remoteEP = new IPEndPoint(ipAddress, targetPort);
+ EndPoint remoteEP = SocketUtil.GetEndPoint("localhost", targetPort);
-
- _remote = new Socket(ipAddress.AddressFamily,
- SocketType.Stream, ProtocolType.Tcp);
+ _remote = SocketUtil.CreateSocket(remoteEP);
_remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
// Connect to the remote endpoint.
diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs
index 5bf73c34..b7638864 100644
--- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs
+++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs
@@ -9,6 +9,7 @@ using Shadowsocks.Controller.Strategy;
using Shadowsocks.Encryption;
using Shadowsocks.Model;
using Shadowsocks.Proxy;
+using Shadowsocks.Util;
namespace Shadowsocks.Controller
{
@@ -363,24 +364,11 @@ namespace Shadowsocks.Controller
CreateRemote();
// Setting up proxy
- IPEndPoint proxyEP;
+ EndPoint proxyEP;
if (_config.useProxy)
{
- IPAddress ipAddress;
- bool parsed = IPAddress.TryParse(_config.proxyServer, out ipAddress);
- if (!parsed)
- {
- /*
- * TODO really necessary to resolve a proxy's address? Maybe from local hosts?
- * also we may simplify it by using dual-mode socket with
- * the approach described in DirectConnect.BeginConnectDest
- */
- IPHostEntry ipHostInfo = Dns.GetHostEntry(_config.proxyServer);
- ipAddress = ipHostInfo.AddressList[0];
- }
-
remote = new Socks5Proxy();
- proxyEP = new IPEndPoint(ipAddress, _config.proxyPort);
+ proxyEP = SocketUtil.GetEndPoint(_config.proxyServer, _config.proxyPort);
}
else
{
@@ -395,7 +383,7 @@ namespace Shadowsocks.Controller
proxyTimer.Enabled = true;
proxyTimer.Proxy = remote;
- proxyTimer.DestEndPoint = ProxyUtils.GetEndPoint(server.server, server.server_port);
+ proxyTimer.DestEndPoint = SocketUtil.GetEndPoint(server.server, server.server_port);
proxyTimer.Server = server;
_proxyConnected = false;
diff --git a/shadowsocks-csharp/Controller/Service/UDPRelay.cs b/shadowsocks-csharp/Controller/Service/UDPRelay.cs
index 5f0d2363..0a5a18ac 100644
--- a/shadowsocks-csharp/Controller/Service/UDPRelay.cs
+++ b/shadowsocks-csharp/Controller/Service/UDPRelay.cs
@@ -7,6 +7,7 @@ using System.Runtime.CompilerServices;
using Shadowsocks.Controller.Strategy;
using Shadowsocks.Encryption;
using Shadowsocks.Model;
+using Shadowsocks.Util;
namespace Shadowsocks.Controller
{
@@ -56,7 +57,7 @@ namespace Shadowsocks.Controller
private byte[] _buffer = new byte[1500];
private IPEndPoint _localEndPoint;
- private IPEndPoint _remoteEndPoint;
+ private EndPoint _remoteEndPoint;
public UDPHandler(Socket local, Server server, IPEndPoint localEndPoint)
{
@@ -64,16 +65,8 @@ namespace Shadowsocks.Controller
_server = server;
_localEndPoint = localEndPoint;
- // TODO async resolving
- IPAddress ipAddress;
- bool parsed = IPAddress.TryParse(server.server, out ipAddress);
- if (!parsed)
- {
- IPHostEntry ipHostInfo = Dns.GetHostEntry(server.server);
- ipAddress = ipHostInfo.AddressList[0];
- }
- _remoteEndPoint = new IPEndPoint(ipAddress, server.server_port);
- _remote = new Socket(_remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
+ _remoteEndPoint = SocketUtil.GetEndPoint(server.server, server.server_port);
+ _remote = SocketUtil.CreateSocket(_remoteEndPoint, ProtocolType.Udp);
}
public void Send(byte[] data, int length)
diff --git a/shadowsocks-csharp/Proxy/DirectConnect.cs b/shadowsocks-csharp/Proxy/DirectConnect.cs
index 071110f1..487adc41 100644
--- a/shadowsocks-csharp/Proxy/DirectConnect.cs
+++ b/shadowsocks-csharp/Proxy/DirectConnect.cs
@@ -2,6 +2,7 @@
using System.Net;
using System.Net.Sockets;
using System.Threading;
+using Shadowsocks.Util;
namespace Shadowsocks.Proxy
{
@@ -52,39 +53,14 @@ namespace Shadowsocks.Proxy
public void BeginConnectDest(EndPoint destEndPoint, AsyncCallback callback, object state)
{
- EndPoint realEndPoint = DestEndPoint = destEndPoint;
-
- /*
- * On windows vista or later, dual-mode socket is supported, so that
- * we don't need to resolve a DnsEndPoint manually.
- * We could just create a dual-mode socket and pass the DnsEndPoint
- * directly to it's BeginConnect and the system will handle it correctlly
- * so that we won't worry about async resolving any more.
- *
- * see: https://blogs.msdn.microsoft.com/webdev/2013/01/08/dual-mode-sockets-never-create-an-ipv4-socket-again/
- *
- * But it seems that we can't use this feature because DnsEndPoint
- * doesn't have a specific AddressFamily before it has been
- * resolved (we don't know whether it's ipv4 or ipv6) and we don't have
- * a dual-mode socket to use on windows xp :(
- */
- var dep = realEndPoint as DnsEndPoint;
- if (dep != null)
- {
- // need to resolve manually
- // TODO async resolving
- IPHostEntry ipHostInfo = Dns.GetHostEntry(dep.Host);
- IPAddress ipAddress = ipHostInfo.AddressList[0];
-
- realEndPoint = new IPEndPoint(ipAddress, dep.Port);
- }
+ DestEndPoint = destEndPoint;
if (_remote == null)
{
- _remote = new Socket(realEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+ _remote = SocketUtil.CreateSocket(destEndPoint);
_remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
}
- _remote.BeginConnect(realEndPoint, callback, state);
+ _remote.BeginConnect(destEndPoint, callback, state);
}
public void EndConnectDest(IAsyncResult asyncResult)
diff --git a/shadowsocks-csharp/Proxy/IProxy.cs b/shadowsocks-csharp/Proxy/IProxy.cs
index 81183110..cc76b543 100644
--- a/shadowsocks-csharp/Proxy/IProxy.cs
+++ b/shadowsocks-csharp/Proxy/IProxy.cs
@@ -35,20 +35,4 @@ namespace Shadowsocks.Proxy
void Close();
}
-
- public static class ProxyUtils
- {
- public static EndPoint GetEndPoint(string host, int port)
- {
- IPAddress ipAddress;
- bool parsed = IPAddress.TryParse(host, out ipAddress);
- if (parsed)
- {
- return new IPEndPoint(ipAddress, port);
- }
-
- // maybe is a domain name
- return new DnsEndPoint(host, port);
- }
- }
}
diff --git a/shadowsocks-csharp/Proxy/Socks5Proxy.cs b/shadowsocks-csharp/Proxy/Socks5Proxy.cs
index 490a6275..adb94402 100644
--- a/shadowsocks-csharp/Proxy/Socks5Proxy.cs
+++ b/shadowsocks-csharp/Proxy/Socks5Proxy.cs
@@ -6,6 +6,7 @@ using System.Net.Sockets;
using System.Text;
using System.Threading;
using Shadowsocks.Controller;
+using Shadowsocks.Util;
namespace Shadowsocks.Proxy
{
@@ -51,7 +52,7 @@ namespace Shadowsocks.Proxy
public void BeginConnectProxy(EndPoint remoteEP, AsyncCallback callback, object state)
{
- _remote = new Socket(remoteEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+ _remote = SocketUtil.CreateSocket(remoteEP);
_remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
var st = new Socks5State();
diff --git a/shadowsocks-csharp/Util/SocketUtil.cs b/shadowsocks-csharp/Util/SocketUtil.cs
new file mode 100644
index 00000000..ad413d49
--- /dev/null
+++ b/shadowsocks-csharp/Util/SocketUtil.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Shadowsocks.Util
+{
+ public static class SocketUtil
+ {
+ private class DnsEndPoint2 : DnsEndPoint
+ {
+ public DnsEndPoint2(string host, int port) : base(host, port)
+ {
+ }
+
+ public DnsEndPoint2(string host, int port, AddressFamily addressFamily) : base(host, port, addressFamily)
+ {
+ }
+
+ public override string ToString()
+ {
+ return this.Host + ":" + this.Port;
+ }
+ }
+
+ public static EndPoint GetEndPoint(string host, int port)
+ {
+ IPAddress ipAddress;
+ bool parsed = IPAddress.TryParse(host, out ipAddress);
+ if (parsed)
+ {
+ return new IPEndPoint(ipAddress, port);
+ }
+
+ // maybe is a domain name
+ return new DnsEndPoint2(host, port);
+ }
+
+ public static Socket CreateSocket(EndPoint endPoint, ProtocolType protocolType = ProtocolType.Tcp)
+ {
+ SocketType socketType;
+ switch (protocolType)
+ {
+ case ProtocolType.Tcp:
+ socketType = SocketType.Stream;
+ break;
+ case ProtocolType.Udp:
+ socketType = SocketType.Dgram;
+ break;
+ default:
+ throw new NotSupportedException("Protocol " + protocolType + " doesn't supported!");
+ }
+
+ if (endPoint is DnsEndPoint)
+ {
+ var socket = new Socket(AddressFamily.InterNetworkV6, socketType, protocolType);
+ socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
+
+ return socket;
+ }
+ else
+ {
+ return new Socket(endPoint.AddressFamily, socketType, protocolType);
+ }
+ }
+ }
+}
diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj
index c4c87271..10e2c7d2 100644
--- a/shadowsocks-csharp/shadowsocks-csharp.csproj
+++ b/shadowsocks-csharp/shadowsocks-csharp.csproj
@@ -176,6 +176,7 @@
+
Form