Compare commits

...

6 commits

Author SHA1 Message Date
TSRBerry
6a785302d6
Merge 1edf780ee1 into 6ce49a2dc7 2024-07-29 02:00:13 +02:00
TSR Berry
1edf780ee1
[WIP] Add ManagedProxySocket implementation 2024-07-29 02:00:05 +02:00
TSR Berry
fcd3f626e5
Move ConvertBsdSocketFlags() to WinSockHelper 2024-07-29 01:52:55 +02:00
TSR Berry
31fc18e3ea
Add ProxyManager 2024-07-28 23:27:02 +02:00
TSR Berry
999128aad8
Add RyuSocks NuGet package 2024-07-28 23:19:51 +02:00
TSR Berry
0ee3fa3981
sockets: Rename Refcount to RefCount 2024-07-28 23:13:57 +02:00
10 changed files with 525 additions and 63 deletions

View file

@ -36,6 +36,7 @@
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" /> <PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" /> <PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="RyuSocks" Version="0.2.0-alpha" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" /> <PackageVersion Include="SharpZipLib" Version="1.4.2" />
@ -49,4 +50,4 @@
<PackageVersion Include="System.Management" Version="8.0.0" /> <PackageVersion Include="System.Management" Version="8.0.0" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -103,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
{ {
lock (_lock) lock (_lock)
{ {
oldFile.Refcount++; oldFile.RefCount++;
return RegisterFileDescriptor(oldFile); return RegisterFileDescriptor(oldFile);
} }
@ -118,9 +118,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
if (file != null) if (file != null)
{ {
file.Refcount--; file.RefCount--;
if (file.Refcount <= 0) if (file.RefCount <= 0)
{ {
file.Dispose(); file.Dispose();
} }

View file

@ -1,6 +1,7 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl; using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl;
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy;
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types; using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
@ -95,10 +96,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
} }
} }
ISocket newBsdSocket = new ManagedSocket(netDomain, (SocketType)type, protocol) ISocket newBsdSocket = ProxyManager.GetSocket(netDomain, (SocketType)type, protocol);
{ newBsdSocket.Blocking = !creationFlags.HasFlag(BsdSocketCreationFlags.NonBlocking);
Blocking = !creationFlags.HasFlag(BsdSocketCreationFlags.NonBlocking),
};
LinuxError errno = LinuxError.SUCCESS; LinuxError errno = LinuxError.SUCCESS;

View file

@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
interface IFileDescriptor : IDisposable interface IFileDescriptor : IDisposable
{ {
bool Blocking { get; set; } bool Blocking { get; set; }
int Refcount { get; set; } int RefCount { get; set; }
LinuxError Read(out int readSize, Span<byte> buffer); LinuxError Read(out int readSize, Span<byte> buffer);

View file

@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
UpdateEventStates(); UpdateEventStates();
} }
public int Refcount { get; set; } public int RefCount { get; set; }
public void Dispose() public void Dispose()
{ {

View file

@ -0,0 +1,408 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
using RyuSocks;
using RyuSocks.Auth;
using RyuSocks.Commands;
using RyuSocks.Types;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{
class ManagedProxySocket : ISocket
{
private static readonly Dictionary<AuthMethod, IProxyAuth> _authMethods = new()
{
{ AuthMethod.NoAuth, new NoAuth() },
};
private readonly bool _isUdpSocket;
private readonly bool _acceptedConnection;
public SocksClient ProxyClient { get; }
// TODO: Make sure Blocking is used properly
public bool Blocking { get; set; }
public int RefCount { get; set; }
// TODO: Assign LocalEndPoint and RemoteEndPoint
public IPEndPoint RemoteEndPoint { get; private set; }
public IPEndPoint LocalEndPoint { get; private set; }
public AddressFamily AddressFamily => ProxyClient.AddressFamily;
public SocketType SocketType => ProxyClient.SocketType;
public ProtocolType ProtocolType => ProxyClient.ProtocolType;
public IntPtr Handle => throw new NotSupportedException("Can't get the handle of a proxy socket.");
public ManagedProxySocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, EndPoint proxyEndpoint)
{
if (addressFamily != proxyEndpoint.AddressFamily && addressFamily != AddressFamily.Unspecified)
{
throw new ArgumentException(
$"Invalid {nameof(System.Net.Sockets.AddressFamily)}", nameof(addressFamily));
}
if (socketType != SocketType.Stream && socketType != SocketType.Dgram)
{
throw new ArgumentException(
$"Invalid {nameof(System.Net.Sockets.SocketType)}", nameof(socketType));
}
if (protocolType != ProtocolType.Tcp && protocolType != ProtocolType.Udp)
{
throw new ArgumentException(
$"Invalid {nameof(System.Net.Sockets.ProtocolType)}", nameof(protocolType));
}
_isUdpSocket = socketType == SocketType.Dgram && protocolType == ProtocolType.Udp;
ProxyClient = proxyEndpoint switch
{
IPEndPoint ipEndPoint => new SocksClient(ipEndPoint) { OfferedAuthMethods = _authMethods },
DnsEndPoint dnsEndPoint => new SocksClient(dnsEndPoint) { OfferedAuthMethods = _authMethods },
_ => throw new ArgumentException($"Unsupported {nameof(EndPoint)} type", nameof(proxyEndpoint))
};
ProxyClient.Authenticate();
RefCount = 1;
}
private ManagedProxySocket(ManagedProxySocket oldSocket, SocksClient proxyClient)
{
ProxyClient = proxyClient;
LocalEndPoint = oldSocket.LocalEndPoint;
RemoteEndPoint = oldSocket.RemoteEndPoint;
_acceptedConnection = true;
RefCount = 1;
}
private static LinuxError ToLinuxError(ReplyField proxyReply)
{
return proxyReply switch
{
ReplyField.Succeeded => LinuxError.SUCCESS,
ReplyField.ServerFailure => LinuxError.ECONNRESET,
ReplyField.ConnectionNotAllowed => LinuxError.ECONNREFUSED,
ReplyField.NetworkUnreachable => LinuxError.ENETUNREACH,
ReplyField.HostUnreachable => LinuxError.EHOSTUNREACH,
ReplyField.ConnectionRefused => LinuxError.ECONNREFUSED,
ReplyField.TTLExpired => LinuxError.EHOSTUNREACH,
ReplyField.CommandNotSupported => LinuxError.EOPNOTSUPP,
ReplyField.AddressTypeNotSupported => LinuxError.EAFNOSUPPORT,
_ => throw new ArgumentOutOfRangeException(nameof(proxyReply))
};
}
public void Dispose()
{
ProxyClient.Dispose();
}
public LinuxError Read(out int readSize, Span<byte> buffer)
{
return Receive(out readSize, buffer, BsdSocketFlags.None);
}
public LinuxError Write(out int writeSize, ReadOnlySpan<byte> buffer)
{
return Send(out writeSize, buffer, BsdSocketFlags.None);
}
public LinuxError Receive(out int receiveSize, Span<byte> buffer, BsdSocketFlags flags)
{
LinuxError result;
bool shouldBlockAfterOperation = false;
if (Blocking && flags.HasFlag(BsdSocketFlags.DontWait))
{
Blocking = false;
shouldBlockAfterOperation = true;
}
byte[] proxyBuffer = new byte[buffer.Length + ProxyClient.GetRequiredWrapperSpace()];
try
{
receiveSize = ProxyClient.Receive(
proxyBuffer,
WinSockHelper.ConvertBsdSocketFlags(flags),
out SocketError errorCode
);
proxyBuffer[..receiveSize].CopyTo(buffer);
result = WinSockHelper.ConvertError((WsaError)errorCode);
}
catch (ProxyException exception)
{
Logger.Error?.Print(
LogClass.ServiceBsd,
$"An error occured while trying to receive data: {exception}"
);
receiveSize = -1;
result = ToLinuxError(exception.ReplyCode);
}
catch (SocketException exception)
{
receiveSize = -1;
result = WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
}
if (shouldBlockAfterOperation)
{
Blocking = true;
}
return result;
}
public LinuxError ReceiveFrom(out int receiveSize, Span<byte> buffer, int size, BsdSocketFlags flags, out IPEndPoint remoteEndPoint)
{
LinuxError result;
remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
bool shouldBlockAfterOperation = false;
byte[] proxyBuffer = new byte[size + ProxyClient.GetRequiredWrapperSpace()];
if (Blocking && flags.HasFlag(BsdSocketFlags.DontWait))
{
Blocking = false;
shouldBlockAfterOperation = true;
}
try
{
EndPoint temp = new IPEndPoint(IPAddress.Any, 0);
receiveSize = ProxyClient.ReceiveFrom(proxyBuffer, WinSockHelper.ConvertBsdSocketFlags(flags), ref temp);
remoteEndPoint = (IPEndPoint)temp;
result = LinuxError.SUCCESS;
}
catch (ProxyException exception)
{
Logger.Error?.Print(
LogClass.ServiceBsd,
$"An error occured while trying to receive data: {exception}"
);
receiveSize = -1;
result = ToLinuxError(exception.ReplyCode);
}
catch (SocketException exception)
{
receiveSize = -1;
result = WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
}
if (shouldBlockAfterOperation)
{
Blocking = true;
}
return result;
}
public LinuxError Send(out int sendSize, ReadOnlySpan<byte> buffer, BsdSocketFlags flags)
{
try
{
sendSize = ProxyClient.Send(buffer, WinSockHelper.ConvertBsdSocketFlags(flags));
return LinuxError.SUCCESS;
}
catch (ProxyException exception)
{
Logger.Error?.Print(
LogClass.ServiceBsd,
$"An error occured while trying to send data: {exception}"
);
sendSize = -1;
return ToLinuxError(exception.ReplyCode);
}
catch (SocketException exception)
{
sendSize = -1;
return WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
}
}
public LinuxError SendTo(out int sendSize, ReadOnlySpan<byte> buffer, int size, BsdSocketFlags flags, IPEndPoint remoteEndPoint)
{
try
{
// NOTE: sendSize might be larger than size and/or buffer.Length.
sendSize = ProxyClient.SendTo(buffer[..size], WinSockHelper.ConvertBsdSocketFlags(flags), remoteEndPoint);
return LinuxError.SUCCESS;
}
catch (ProxyException exception)
{
Logger.Error?.Print(
LogClass.ServiceBsd,
$"An error occured while trying to send data: {exception}"
);
sendSize = -1;
return ToLinuxError(exception.ReplyCode);
}
catch (SocketException exception)
{
sendSize = -1;
return WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
}
}
public LinuxError RecvMMsg(out int vlen, BsdMMsgHdr message, BsdSocketFlags flags, TimeVal timeout)
{
throw new NotImplementedException();
}
public LinuxError SendMMsg(out int vlen, BsdMMsgHdr message, BsdSocketFlags flags)
{
throw new NotImplementedException();
}
public LinuxError GetSocketOption(BsdSocketOption option, SocketOptionLevel level, Span<byte> optionValue)
{
// TODO: Call ProxyClient.GetSocketOption() when it's implemented
throw new NotImplementedException();
}
public LinuxError SetSocketOption(BsdSocketOption option, SocketOptionLevel level, ReadOnlySpan<byte> optionValue)
{
// TODO: Call ProxyClient.SetSocketOption() when it's implemented
throw new NotImplementedException();
}
public bool Poll(int microSeconds, SelectMode mode)
{
// TODO: Call ProxyClient.Poll() when it's implemented
throw new NotImplementedException();
}
public LinuxError Bind(IPEndPoint localEndPoint)
{
ProxyClient.RequestCommand = _isUdpSocket ? ProxyCommand.UdpAssociate : ProxyCommand.Bind;
try
{
ProxyClient.Bind(localEndPoint);
}
catch (ProxyException exception)
{
Logger.Error?.Print(
LogClass.ServiceBsd,
$"Request for {ProxyClient.RequestCommand} command failed: {exception}"
);
return ToLinuxError(exception.ReplyCode);
}
catch (SocketException exception)
{
return WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
}
return LinuxError.SUCCESS;
}
public LinuxError Connect(IPEndPoint remoteEndPoint)
{
ProxyClient.RequestCommand = ProxyCommand.Connect;
try
{
ProxyClient.Connect(remoteEndPoint.Address, remoteEndPoint.Port);
}
catch (ProxyException exception)
{
Logger.Error?.Print(
LogClass.ServiceBsd,
$"Request for {ProxyClient.RequestCommand} command failed: {exception}"
);
return ToLinuxError(exception.ReplyCode);
}
catch (SocketException exception)
{
return WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
}
return LinuxError.SUCCESS;
}
public LinuxError Listen(int backlog)
{
// NOTE: Only one client can connect with the default SOCKS5 commands.
if (ProxyClient.RequestCommand != ProxyCommand.Bind)
{
return LinuxError.EOPNOTSUPP;
}
return LinuxError.SUCCESS;
}
public LinuxError Accept(out ISocket newSocket)
{
newSocket = null;
if (ProxyClient.RequestCommand != ProxyCommand.Bind)
{
return LinuxError.EOPNOTSUPP;
}
// NOTE: Only one client can connect with the default SOCKS5 commands.
if (_acceptedConnection)
{
return LinuxError.EOPNOTSUPP;
}
try
{
SocksClient newProxyClient = ProxyClient.Accept();
newSocket = new ManagedProxySocket(this, newProxyClient);
}
catch (ProxyException exception)
{
Logger.Error?.Print(
LogClass.ServiceBsd,
$"Failed to accept client connection: {exception}"
);
return ToLinuxError(exception.ReplyCode);
}
catch (SocketException exception)
{
return WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
}
return LinuxError.SUCCESS;
}
public void Disconnect()
{
// TODO: Call ProxyClient.Disconnect() when it's implemented
}
public LinuxError Shutdown(BsdSocketShutdownFlags how)
{
// TODO: Call ProxyClient.Shutdown() when it's implemented
return LinuxError.SUCCESS;
}
public void Close()
{
ProxyClient.Close();
}
}
}

View file

@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{ {
class ManagedSocket : ISocket class ManagedSocket : ISocket
{ {
public int Refcount { get; set; } public int RefCount { get; set; }
public AddressFamily AddressFamily => Socket.AddressFamily; public AddressFamily AddressFamily => Socket.AddressFamily;
@ -32,57 +32,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
public ManagedSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) public ManagedSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
{ {
Socket = new Socket(addressFamily, socketType, protocolType); Socket = new Socket(addressFamily, socketType, protocolType);
Refcount = 1; RefCount = 1;
} }
private ManagedSocket(Socket socket) private ManagedSocket(Socket socket)
{ {
Socket = socket; Socket = socket;
Refcount = 1; RefCount = 1;
}
private static SocketFlags ConvertBsdSocketFlags(BsdSocketFlags bsdSocketFlags)
{
SocketFlags socketFlags = SocketFlags.None;
if (bsdSocketFlags.HasFlag(BsdSocketFlags.Oob))
{
socketFlags |= SocketFlags.OutOfBand;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.Peek))
{
socketFlags |= SocketFlags.Peek;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.DontRoute))
{
socketFlags |= SocketFlags.DontRoute;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.Trunc))
{
socketFlags |= SocketFlags.Truncated;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.CTrunc))
{
socketFlags |= SocketFlags.ControlDataTruncated;
}
bsdSocketFlags &= ~(BsdSocketFlags.Oob |
BsdSocketFlags.Peek |
BsdSocketFlags.DontRoute |
BsdSocketFlags.DontWait |
BsdSocketFlags.Trunc |
BsdSocketFlags.CTrunc);
if (bsdSocketFlags != BsdSocketFlags.None)
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported socket flags: {bsdSocketFlags}");
}
return socketFlags;
} }
public LinuxError Accept(out ISocket newSocket) public LinuxError Accept(out ISocket newSocket)
@ -199,7 +155,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
shouldBlockAfterOperation = true; shouldBlockAfterOperation = true;
} }
receiveSize = Socket.Receive(buffer, ConvertBsdSocketFlags(flags)); receiveSize = Socket.Receive(buffer, WinSockHelper.ConvertBsdSocketFlags(flags));
result = LinuxError.SUCCESS; result = LinuxError.SUCCESS;
} }
@ -243,7 +199,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
return LinuxError.EOPNOTSUPP; return LinuxError.EOPNOTSUPP;
} }
receiveSize = Socket.ReceiveFrom(buffer[..size], ConvertBsdSocketFlags(flags), ref temp); receiveSize = Socket.ReceiveFrom(buffer[..size], WinSockHelper.ConvertBsdSocketFlags(flags), ref temp);
remoteEndPoint = (IPEndPoint)temp; remoteEndPoint = (IPEndPoint)temp;
result = LinuxError.SUCCESS; result = LinuxError.SUCCESS;
@ -267,7 +223,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{ {
try try
{ {
sendSize = Socket.Send(buffer, ConvertBsdSocketFlags(flags)); sendSize = Socket.Send(buffer, WinSockHelper.ConvertBsdSocketFlags(flags));
return LinuxError.SUCCESS; return LinuxError.SUCCESS;
} }
@ -283,7 +239,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{ {
try try
{ {
sendSize = Socket.SendTo(buffer[..size], ConvertBsdSocketFlags(flags), remoteEndPoint); sendSize = Socket.SendTo(buffer[..size], WinSockHelper.ConvertBsdSocketFlags(flags), remoteEndPoint);
return LinuxError.SUCCESS; return LinuxError.SUCCESS;
} }
@ -493,7 +449,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
try try
{ {
int receiveSize = Socket.Receive(ConvertMessagesToBuffer(message), ConvertBsdSocketFlags(flags), out SocketError socketError); int receiveSize = Socket.Receive(ConvertMessagesToBuffer(message), WinSockHelper.ConvertBsdSocketFlags(flags), out SocketError socketError);
if (receiveSize > 0) if (receiveSize > 0)
{ {
@ -531,7 +487,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
try try
{ {
int sendSize = Socket.Send(ConvertMessagesToBuffer(message), ConvertBsdSocketFlags(flags), out SocketError socketError); int sendSize = Socket.Send(ConvertMessagesToBuffer(message), WinSockHelper.ConvertBsdSocketFlags(flags), out SocketError socketError);
if (sendSize > 0) if (sendSize > 0)
{ {

View file

@ -1,3 +1,4 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types; using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -343,5 +344,49 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
return LinuxError.SUCCESS; return LinuxError.SUCCESS;
} }
public static SocketFlags ConvertBsdSocketFlags(BsdSocketFlags bsdSocketFlags)
{
SocketFlags socketFlags = SocketFlags.None;
if (bsdSocketFlags.HasFlag(BsdSocketFlags.Oob))
{
socketFlags |= SocketFlags.OutOfBand;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.Peek))
{
socketFlags |= SocketFlags.Peek;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.DontRoute))
{
socketFlags |= SocketFlags.DontRoute;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.Trunc))
{
socketFlags |= SocketFlags.Truncated;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.CTrunc))
{
socketFlags |= SocketFlags.ControlDataTruncated;
}
bsdSocketFlags &= ~(BsdSocketFlags.Oob |
BsdSocketFlags.Peek |
BsdSocketFlags.DontRoute |
BsdSocketFlags.DontWait |
BsdSocketFlags.Trunc |
BsdSocketFlags.CTrunc);
if (bsdSocketFlags != BsdSocketFlags.None)
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported socket flags: {bsdSocketFlags}");
}
return socketFlags;
}
} }
} }

View file

@ -0,0 +1,52 @@
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy
{
public static class ProxyManager
{
private static readonly Dictionary<string, EndPoint> _proxyEndpoints = new();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string GetKey(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
{
return string.Join("-", new[] { (int)addressFamily, (int)socketType, (int)protocolType });
}
internal static ISocket GetSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
{
if (_proxyEndpoints.TryGetValue(GetKey(addressFamily, socketType, protocolType), out EndPoint endPoint))
{
return new ManagedProxySocket(addressFamily, socketType, protocolType, endPoint);
}
return new ManagedSocket(addressFamily, socketType, protocolType);
}
public static void AddOrUpdate(EndPoint endPoint,
AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
{
_proxyEndpoints[GetKey(addressFamily, socketType, protocolType)] = endPoint;
}
public static void AddOrUpdate(IPAddress address, int port,
AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
{
_proxyEndpoints[GetKey(addressFamily, socketType, protocolType)] = new IPEndPoint(address, port);
}
public static void AddOrUpdate(string host, int port,
AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
{
_proxyEndpoints[GetKey(addressFamily, socketType, protocolType)] = new DnsEndPoint(host, port);
}
public static bool Remove(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
{
return _proxyEndpoints.Remove(GetKey(addressFamily, socketType, protocolType));
}
}
}

View file

@ -27,6 +27,7 @@
<PackageReference Include="SixLabors.ImageSharp" /> <PackageReference Include="SixLabors.ImageSharp" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" />
<PackageReference Include="NetCoreServer" /> <PackageReference Include="NetCoreServer" />
<PackageReference Include="RyuSocks" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>