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