Browse Source

fix udp uplink.

pull/2925/head
Student Main 4 years ago
parent
commit
465947dbbb
No known key found for this signature in database GPG Key ID: AA78519C208C8742
2 changed files with 37 additions and 54 deletions
  1. +20
    -36
      shadowsocks-csharp/Controller/Service/UDPListener.cs
  2. +17
    -18
      shadowsocks-csharp/Controller/Service/UDPRelay.cs

+ 20
- 36
shadowsocks-csharp/Controller/Service/UDPListener.cs View File

@@ -4,6 +4,8 @@ using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using Shadowsocks.Model;

@@ -49,6 +51,7 @@ namespace Shadowsocks.Controller
bool _shareOverLAN;
Socket _udpSocket;
IEnumerable<IDatagramService> _services;
CancellationTokenSource tokenSource = new CancellationTokenSource();

public UDPListener(Configuration config, IEnumerable<IDatagramService> services)
{
@@ -84,54 +87,35 @@ namespace Shadowsocks.Controller
logger.Info($"Shadowsocks started UDP ({UpdateChecker.Version})");
logger.Debug(Encryption.EncryptorFactory.DumpRegisteredEncryptor());
UDPState udpState = new UDPState(_udpSocket);
_udpSocket.BeginReceiveFrom(udpState.buffer, 0, udpState.buffer.Length, 0, ref udpState.remoteEndPoint, new AsyncCallback(RecvFromCallback), udpState);

}

public void Stop()
{
_udpSocket?.Close();
foreach (var s in _services)
{
s.Stop();
}
// _udpSocket.BeginReceiveFrom(udpState.buffer, 0, udpState.buffer.Length, 0, ref udpState.remoteEndPoint, new AsyncCallback(RecvFromCallback), udpState);
Task.Run(() => WorkLoop(tokenSource.Token));
}

public void RecvFromCallback(IAsyncResult ar)
private async Task WorkLoop(CancellationToken token)
{
UDPState state = (UDPState)ar.AsyncState;
var socket = state.socket;
try
byte[] buffer = new byte[4096];
EndPoint remote = new IPEndPoint(_udpSocket.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any, 0);
while (!token.IsCancellationRequested)
{
int bytesRead = socket.EndReceiveFrom(ar, ref state.remoteEndPoint);
var result = await _udpSocket.ReceiveFromAsync(buffer, SocketFlags.None, remote);
var len = result.ReceivedBytes;
foreach (IDatagramService service in _services)
{
if (service.Handle(state.buffer, bytesRead, socket, state))
if (service.Handle(buffer, len, _udpSocket, remote))
{
break;
}
}
}
catch (ObjectDisposedException)
{
}
catch (Exception ex)
{
logger.Debug(ex);
}
finally
}

public void Stop()
{
tokenSource.Cancel();
_udpSocket?.Close();
foreach (var s in _services)
{
try
{
socket.BeginReceiveFrom(state.buffer, 0, state.buffer.Length, 0, ref state.remoteEndPoint, new AsyncCallback(RecvFromCallback), state);
}
catch (ObjectDisposedException)
{
// do nothing
}
catch (Exception)
{
}
s.Stop();
}
}
}


+ 17
- 18
shadowsocks-csharp/Controller/Service/UDPRelay.cs View File

@@ -44,8 +44,8 @@ namespace Shadowsocks.Controller
{
return false;
}
UDPListener.UDPState udpState = (UDPListener.UDPState)state;
IPEndPoint remoteEndPoint = (IPEndPoint)udpState.remoteEndPoint;
// UDPListener.UDPState udpState = (UDPListener.UDPState)state;
IPEndPoint remoteEndPoint = (IPEndPoint)state;
UDPHandler handler = _cache.get(remoteEndPoint);
if (handler == null)
{
@@ -70,16 +70,16 @@ namespace Shadowsocks.Controller
private IPEndPoint _localEndPoint;
private IPEndPoint _remoteEndPoint;
private IPAddress GetIPAddress()
private IPAddress ListenAddress
{
switch (_remote.AddressFamily)
get
{
case AddressFamily.InterNetwork:
return IPAddress.Any;
case AddressFamily.InterNetworkV6:
return IPAddress.IPv6Any;
default:
return IPAddress.Any;
return _remote.AddressFamily switch
{
AddressFamily.InterNetwork => IPAddress.Any,
AddressFamily.InterNetworkV6 => IPAddress.IPv6Any,
_ => throw new NotSupportedException(),
};
}
}
@@ -99,24 +99,23 @@ namespace Shadowsocks.Controller
}
_remoteEndPoint = new IPEndPoint(ipAddress, server.server_port);
_remote = new Socket(_remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
_remote.Bind(new IPEndPoint(GetIPAddress(), 0));
_remote.Bind(new IPEndPoint(ListenAddress, 0));
}
public void Send(byte[] data, int length)
{
IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password);
// byte[] dataIn = new byte[length - 3];
// Array.Copy(data, 3, dataIn, 0, length - 3);
byte[] dataOut = new byte[65536]; // enough space for AEAD ciphers
// encryptor.EncryptUDP(dataIn, length - 3, dataOut, out outlen);
int outlen = encryptor.EncryptUDP(data.AsSpan(3), dataOut);
var slicedData = data.AsSpan(0, length);
byte[] dataOut = new byte[slicedData.Length + 1000];
var dataToSend = slicedData[3..];
int outlen = encryptor.EncryptUDP(slicedData[3..], dataOut);
logger.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay");
_remote?.SendTo(dataOut, outlen, SocketFlags.None, _remoteEndPoint);
}
public void Receive()
{
EndPoint remoteEndPoint = new IPEndPoint(GetIPAddress(), 0);
EndPoint remoteEndPoint = new IPEndPoint(ListenAddress, 0);
logger.Debug($"++++++Receive Server Port, size:" + _buffer.Length);
_remote?.BeginReceiveFrom(_buffer, 0, _buffer.Length, 0, ref remoteEndPoint, new AsyncCallback(RecvFromCallback), null);
}
@@ -126,7 +125,7 @@ namespace Shadowsocks.Controller
try
{
if (_remote == null) return;
EndPoint remoteEndPoint = new IPEndPoint(GetIPAddress(), 0);
EndPoint remoteEndPoint = new IPEndPoint(ListenAddress, 0);
int bytesRead = _remote.EndReceiveFrom(ar, ref remoteEndPoint);
byte[] dataOut = new byte[bytesRead];


Loading…
Cancel
Save