Files
shadowsocks-windows/shadowsocks-csharp/Proxy/DirectConnect.cs
T
noisyfox 53ce1948e4 Unified ipv4, ipv6 and domain connections.
-Use dual-mode socket & DnsEndPoint to handle all domain name connection.
-Move all socket creation into one single function.

So that we could treat domain name just like ipv4 & ipv6 address.
This also solves the async domain solving problem because the os will
hanlde it for us.
2016-08-16 20:40:09 +10:00

104 lines
2.9 KiB
C#

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Shadowsocks.Util;
namespace Shadowsocks.Proxy
{
public class DirectConnect : IProxy
{
private class FakeAsyncResult : IAsyncResult
{
public FakeAsyncResult(object state)
{
AsyncState = state;
}
public bool IsCompleted { get; } = true;
public WaitHandle AsyncWaitHandle { get; } = null;
public object AsyncState { get; }
public bool CompletedSynchronously { get; } = true;
}
private class FakeEndPoint : EndPoint
{
public override AddressFamily AddressFamily { get; } = AddressFamily.Unspecified;
public override string ToString()
{
return "null proxy";
}
}
private Socket _remote;
public EndPoint LocalEndPoint => _remote.LocalEndPoint;
public EndPoint ProxyEndPoint { get; } = new FakeEndPoint();
public EndPoint DestEndPoint { get; private set; }
public void BeginConnectProxy(EndPoint remoteEP, AsyncCallback callback, object state)
{
// do nothing
var r = new FakeAsyncResult(state);
callback?.Invoke(r);
}
public void EndConnectProxy(IAsyncResult asyncResult)
{
// do nothing
}
public void BeginConnectDest(EndPoint destEndPoint, AsyncCallback callback, object state)
{
DestEndPoint = destEndPoint;
if (_remote == null)
{
_remote = SocketUtil.CreateSocket(destEndPoint);
_remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
}
_remote.BeginConnect(destEndPoint, callback, state);
}
public void EndConnectDest(IAsyncResult asyncResult)
{
_remote?.EndConnect(asyncResult);
}
public void BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback,
object state)
{
_remote?.BeginSend(buffer, offset, size, socketFlags, callback, state);
}
public int EndSend(IAsyncResult asyncResult)
{
return _remote.EndSend(asyncResult);
}
public void BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback,
object state)
{
_remote?.BeginReceive(buffer, offset, size, socketFlags, callback, state);
}
public int EndReceive(IAsyncResult asyncResult)
{
return _remote.EndReceive(asyncResult);
}
public void Shutdown(SocketShutdown how)
{
_remote?.Shutdown(how);
}
public void Close()
{
_remote?.Close();
}
}
}