From 282892634e2ea123a79c4333a42efebf624dba1d Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Sun, 26 Nov 2023 23:39:38 +0100 Subject: [PATCH 01/15] sockets: Rename Refcount to RefCount --- src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/BsdContext.cs | 6 +++--- src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IFileDescriptor.cs | 2 +- .../HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs | 2 +- .../HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/BsdContext.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/BsdContext.cs index 7ecd6835db..b03fba375c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/BsdContext.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/BsdContext.cs @@ -103,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { lock (_lock) { - oldFile.Refcount++; + oldFile.RefCount++; return RegisterFileDescriptor(oldFile); } @@ -118,9 +118,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd if (file != null) { - file.Refcount--; + file.RefCount--; - if (file.Refcount <= 0) + if (file.RefCount <= 0) { file.Dispose(); } diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IFileDescriptor.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IFileDescriptor.cs index 6c00d5e118..4ad5806787 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IFileDescriptor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IFileDescriptor.cs @@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd interface IFileDescriptor : IDisposable { bool Blocking { get; set; } - int Refcount { get; set; } + int RefCount { get; set; } LinuxError Read(out int readSize, Span buffer); diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs index 5b9e6811d3..7c599335f1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs @@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl UpdateEventStates(); } - public int Refcount { get; set; } + public int RefCount { get; set; } public void Dispose() { diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs index c42b7201bf..1079fde6e9 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs @@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { class ManagedSocket : ISocket { - public int Refcount { get; set; } + public int RefCount { get; set; } public AddressFamily AddressFamily => Socket.AddressFamily; @@ -32,13 +32,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl public ManagedSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) { Socket = new Socket(addressFamily, socketType, protocolType); - Refcount = 1; + RefCount = 1; } private ManagedSocket(Socket socket) { Socket = socket; - Refcount = 1; + RefCount = 1; } private static SocketFlags ConvertBsdSocketFlags(BsdSocketFlags bsdSocketFlags) From aea32c29aa229008c1ae69b7f400dda9ba92eb25 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Sun, 28 Jul 2024 23:19:51 +0200 Subject: [PATCH 02/15] Add RyuSocks NuGet package --- Directory.Packages.props | 3 ++- src/Ryujinx.HLE/Ryujinx.HLE.csproj | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index e722dd8838..72d2442a35 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,6 +36,7 @@ + @@ -49,4 +50,4 @@ - \ No newline at end of file + diff --git a/src/Ryujinx.HLE/Ryujinx.HLE.csproj b/src/Ryujinx.HLE/Ryujinx.HLE.csproj index 0fcf9e4b57..ef9834aa2c 100644 --- a/src/Ryujinx.HLE/Ryujinx.HLE.csproj +++ b/src/Ryujinx.HLE/Ryujinx.HLE.csproj @@ -27,6 +27,7 @@ + From 49acca8cf7464c1ef8db34bea59877af93ec0e06 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Sun, 28 Jul 2024 23:27:02 +0200 Subject: [PATCH 03/15] Add ProxyManager --- .../HOS/Services/Sockets/Bsd/IClient.cs | 7 ++- .../Sockets/Bsd/Proxy/ProxyManager.cs | 49 +++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs index 21d48288ec..8616c4ceb9 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs @@ -1,6 +1,7 @@ using Ryujinx.Common; using Ryujinx.Common.Logging; 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.Memory; using System; @@ -95,10 +96,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd } } - ISocket newBsdSocket = new ManagedSocket(netDomain, (SocketType)type, protocol) - { - Blocking = !creationFlags.HasFlag(BsdSocketCreationFlags.NonBlocking), - }; + ISocket newBsdSocket = ProxyManager.GetSocket(netDomain, (SocketType)type, protocol); + newBsdSocket.Blocking = !creationFlags.HasFlag(BsdSocketCreationFlags.NonBlocking); LinuxError errno = LinuxError.SUCCESS; diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs new file mode 100644 index 0000000000..a9a2192736 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs @@ -0,0 +1,49 @@ +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 _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) + { + // TODO: Return proxy socket if AddressFamily, SocketType and ProtocolType match. + + 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)); + } + } +} From c89a1b2d46fda48f2af510dd6fe868ec8e96f304 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Mon, 29 Jul 2024 01:52:55 +0200 Subject: [PATCH 04/15] Move ConvertBsdSocketFlags() to WinSockHelper --- .../Sockets/Bsd/Impl/ManagedSocket.cs | 56 ++----------------- .../Sockets/Bsd/Impl/WinSockHelper.cs | 45 +++++++++++++++ 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs index 1079fde6e9..15c4743dad 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs @@ -41,50 +41,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl 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) { try @@ -199,7 +155,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl shouldBlockAfterOperation = true; } - receiveSize = Socket.Receive(buffer, ConvertBsdSocketFlags(flags)); + receiveSize = Socket.Receive(buffer, WinSockHelper.ConvertBsdSocketFlags(flags)); result = LinuxError.SUCCESS; } @@ -243,7 +199,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl 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; result = LinuxError.SUCCESS; @@ -267,7 +223,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { try { - sendSize = Socket.Send(buffer, ConvertBsdSocketFlags(flags)); + sendSize = Socket.Send(buffer, WinSockHelper.ConvertBsdSocketFlags(flags)); return LinuxError.SUCCESS; } @@ -283,7 +239,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { try { - sendSize = Socket.SendTo(buffer[..size], ConvertBsdSocketFlags(flags), remoteEndPoint); + sendSize = Socket.SendTo(buffer[..size], WinSockHelper.ConvertBsdSocketFlags(flags), remoteEndPoint); return LinuxError.SUCCESS; } @@ -493,7 +449,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl 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) { @@ -531,7 +487,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl 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) { diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs index e2ef75f807..c41a565fd9 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types; using System; using System.Collections.Generic; @@ -343,5 +344,49 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl 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; + } } } From ac67adae86c34584000fa6f15cf834839a8e6ccf Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Mon, 29 Jul 2024 01:54:07 +0200 Subject: [PATCH 05/15] [WIP] Add ManagedProxySocket implementation --- .../Sockets/Bsd/Impl/ManagedProxySocket.cs | 408 ++++++++++++++++++ .../Sockets/Bsd/Proxy/ProxyManager.cs | 5 +- 2 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs new file mode 100644 index 0000000000..b2461836ae --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs @@ -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 _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 buffer) + { + return Receive(out readSize, buffer, BsdSocketFlags.None); + } + + public LinuxError Write(out int writeSize, ReadOnlySpan buffer) + { + return Send(out writeSize, buffer, BsdSocketFlags.None); + } + + public LinuxError Receive(out int receiveSize, Span 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 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 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 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 optionValue) + { + // TODO: Call ProxyClient.GetSocketOption() when it's implemented + throw new NotImplementedException(); + } + + public LinuxError SetSocketOption(BsdSocketOption option, SocketOptionLevel level, ReadOnlySpan 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(); + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs index a9a2192736..c5a0b5ed3a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs @@ -18,7 +18,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy internal static ISocket GetSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) { - // TODO: Return proxy socket if AddressFamily, SocketType and ProtocolType match. + if (_proxyEndpoints.TryGetValue(GetKey(addressFamily, socketType, protocolType), out EndPoint endPoint)) + { + return new ManagedProxySocket(addressFamily, socketType, protocolType, endPoint); + } return new ManagedSocket(addressFamily, socketType, protocolType); } From fe0c34c639a9912898ce982d9b4f1637d5b5875f Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Wed, 14 Aug 2024 03:53:56 +0200 Subject: [PATCH 06/15] Update RyuSocks to v0.3.1-alpha --- Directory.Packages.props | 4 +- .../Sockets/Bsd/Impl/ManagedProxySocket.cs | 100 ++++++++++++++---- 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 72d2442a35..461388511b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,7 +36,7 @@ - + @@ -50,4 +50,4 @@ - + \ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs index b2461836ae..73608c0308 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs @@ -23,13 +23,11 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl public SocksClient ProxyClient { get; } - // TODO: Make sure Blocking is used properly - public bool Blocking { get; set; } + public bool Blocking { get => ProxyClient.Blocking; set => ProxyClient.Blocking = value; } public int RefCount { get; set; } - // TODO: Assign LocalEndPoint and RemoteEndPoint - public IPEndPoint RemoteEndPoint { get; private set; } - public IPEndPoint LocalEndPoint { get; private set; } + public IPEndPoint RemoteEndPoint => (IPEndPoint)ProxyClient.ProxiedRemoteEndPoint; + public IPEndPoint LocalEndPoint => (IPEndPoint)ProxyClient.ProxiedLocalEndPoint; public AddressFamily AddressFamily => ProxyClient.AddressFamily; public SocketType SocketType => ProxyClient.SocketType; @@ -70,11 +68,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl RefCount = 1; } - private ManagedProxySocket(ManagedProxySocket oldSocket, SocksClient proxyClient) + private ManagedProxySocket(SocksClient proxyClient) { ProxyClient = proxyClient; - LocalEndPoint = oldSocket.LocalEndPoint; - RemoteEndPoint = oldSocket.RemoteEndPoint; _acceptedConnection = true; RefCount = 1; } @@ -273,22 +269,82 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl throw new NotImplementedException(); } + /// + /// Adapted from + /// public LinuxError GetSocketOption(BsdSocketOption option, SocketOptionLevel level, Span optionValue) { - // TODO: Call ProxyClient.GetSocketOption() when it's implemented - throw new NotImplementedException(); + try + { + LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: false); + + if (result != LinuxError.SUCCESS) + { + Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid GetSockOpt Option: {option} Level: {level}"); + + return result; + } + + if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName)) + { + Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt Option: {option} Level: {level}"); + optionValue.Clear(); + + return LinuxError.SUCCESS; + } + + byte[] tempOptionValue = new byte[optionValue.Length]; + + ProxyClient.GetSocketOption(level, optionName, tempOptionValue); + + tempOptionValue.AsSpan().CopyTo(optionValue); + + return LinuxError.SUCCESS; + } + catch (SocketException exception) + { + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); + } } + /// + /// Adapted from + /// public LinuxError SetSocketOption(BsdSocketOption option, SocketOptionLevel level, ReadOnlySpan optionValue) { - // TODO: Call ProxyClient.SetSocketOption() when it's implemented - throw new NotImplementedException(); + try + { + LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: true); + + if (result != LinuxError.SUCCESS) + { + Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid SetSockOpt Option: {option} Level: {level}"); + + return result; + } + + if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName)) + { + Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt Option: {option} Level: {level}"); + + return LinuxError.SUCCESS; + } + + byte[] value = optionValue.ToArray(); + + ProxyClient.SetSocketOption(level, optionName, value); + + return LinuxError.SUCCESS; + } + catch (SocketException exception) + { + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); + } } public bool Poll(int microSeconds, SelectMode mode) { - // TODO: Call ProxyClient.Poll() when it's implemented - throw new NotImplementedException(); + return ProxyClient.Poll(microSeconds, mode); } public LinuxError Bind(IPEndPoint localEndPoint) @@ -370,7 +426,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl try { SocksClient newProxyClient = ProxyClient.Accept(); - newSocket = new ManagedProxySocket(this, newProxyClient); + newSocket = new ManagedProxySocket(newProxyClient); } catch (ProxyException exception) { @@ -391,13 +447,21 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl public void Disconnect() { - // TODO: Call ProxyClient.Disconnect() when it's implemented + ProxyClient.Disconnect(); } public LinuxError Shutdown(BsdSocketShutdownFlags how) { - // TODO: Call ProxyClient.Shutdown() when it's implemented - return LinuxError.SUCCESS; + try + { + ProxyClient.Shutdown((SocketShutdown)how); + + return LinuxError.SUCCESS; + } + catch (SocketException exception) + { + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); + } } public void Close() From f14df5cbb89a48f9553ac2da519015ab061b5c8c Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Wed, 14 Aug 2024 03:54:37 +0200 Subject: [PATCH 07/15] Add ManagedProxySocketPollManager impl --- .../HOS/Services/Sockets/Bsd/IClient.cs | 1 + .../Bsd/Impl/ManagedProxySocketPollManager.cs | 211 ++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocketPollManager.cs diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs index 8616c4ceb9..ac989be927 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs @@ -21,6 +21,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { EventFileDescriptorPollManager.Instance, ManagedSocketPollManager.Instance, + ManagedProxySocketPollManager.Instance, }; private BsdContext _context; diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocketPollManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocketPollManager.cs new file mode 100644 index 0000000000..fd7e730eea --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocketPollManager.cs @@ -0,0 +1,211 @@ +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types; +using System.Collections.Generic; +using System.Net.Sockets; + +namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl +{ + class ManagedProxySocketPollManager : IPollManager + { + private static ManagedProxySocketPollManager _instance; + + public static ManagedProxySocketPollManager Instance + { + get + { + _instance ??= new ManagedProxySocketPollManager(); + + return _instance; + } + } + + public bool IsCompatible(PollEvent evnt) + { + return evnt.FileDescriptor is ManagedProxySocket; + } + + public LinuxError Poll(List events, int timeoutMilliseconds, out int updatedCount) + { + Dictionary> eventDict = new() + { + { SelectMode.SelectRead, [] }, + { SelectMode.SelectWrite, [] }, + { SelectMode.SelectError, [] }, + }; + + updatedCount = 0; + + foreach (PollEvent evnt in events) + { + ManagedProxySocket socket = (ManagedProxySocket)evnt.FileDescriptor; + + bool isValidEvent = evnt.Data.InputEvents == 0; + + eventDict[SelectMode.SelectError].Add(socket); + + if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0) + { + eventDict[SelectMode.SelectRead].Add(socket); + + isValidEvent = true; + } + + if ((evnt.Data.InputEvents & PollEventTypeMask.UrgentInput) != 0) + { + eventDict[SelectMode.SelectRead].Add(socket); + + isValidEvent = true; + } + + if ((evnt.Data.InputEvents & PollEventTypeMask.Output) != 0) + { + eventDict[SelectMode.SelectWrite].Add(socket); + + isValidEvent = true; + } + + if (!isValidEvent) + { + Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Poll input event type: {evnt.Data.InputEvents}"); + return LinuxError.EINVAL; + } + } + + try + { + int actualTimeoutMicroseconds = timeoutMilliseconds == -1 ? -1 : timeoutMilliseconds * 1000; + int totalEvents = eventDict[SelectMode.SelectRead].Count + eventDict[SelectMode.SelectWrite].Count + eventDict[SelectMode.SelectError].Count; + // TODO: Maybe check all events first, wait for the timeout and then check the failed ones again? + int timeoutMicrosecondsPerEvent = actualTimeoutMicroseconds == -1 ? -1 : actualTimeoutMicroseconds / totalEvents; + + foreach ((SelectMode selectMode, List eventList) in eventDict) + { + List newEventList = []; + + foreach (ManagedProxySocket eventSocket in eventList) + { + if (eventSocket.Poll(timeoutMicrosecondsPerEvent, selectMode)) + { + newEventList.Add(eventSocket); + } + } + + eventDict[selectMode] = newEventList; + } + } + catch (SocketException exception) + { + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); + } + + foreach (PollEvent evnt in events) + { + ManagedProxySocket socket = ((ManagedProxySocket)evnt.FileDescriptor); + + PollEventTypeMask outputEvents = evnt.Data.OutputEvents & ~evnt.Data.InputEvents; + + if (eventDict[SelectMode.SelectError].Contains(socket)) + { + outputEvents |= PollEventTypeMask.Error; + + // TODO: Check ProxyClient.Connected and ProxyClient.IsBound when implemented. + // See ManagedSocketPollManager + } + + if (eventDict[SelectMode.SelectRead].Contains(socket)) + { + if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0) + { + outputEvents |= PollEventTypeMask.Input; + } + } + + if (eventDict[SelectMode.SelectWrite].Contains(socket)) + { + outputEvents |= PollEventTypeMask.Output; + } + + evnt.Data.OutputEvents = outputEvents; + } + + updatedCount = eventDict[SelectMode.SelectRead].Count + eventDict[SelectMode.SelectWrite].Count + eventDict[SelectMode.SelectError].Count; + + return LinuxError.SUCCESS; + } + + public LinuxError Select(List events, int timeout, out int updatedCount) + { + Dictionary> eventDict = new() + { + { SelectMode.SelectRead, [] }, + { SelectMode.SelectWrite, [] }, + { SelectMode.SelectError, [] }, + }; + + updatedCount = 0; + + foreach (PollEvent pollEvent in events) + { + ManagedProxySocket socket = (ManagedProxySocket)pollEvent.FileDescriptor; + + if (pollEvent.Data.InputEvents.HasFlag(PollEventTypeMask.Input)) + { + eventDict[SelectMode.SelectRead].Add(socket); + } + + if (pollEvent.Data.InputEvents.HasFlag(PollEventTypeMask.Output)) + { + eventDict[SelectMode.SelectWrite].Add(socket); + } + + if (pollEvent.Data.InputEvents.HasFlag(PollEventTypeMask.Error)) + { + eventDict[SelectMode.SelectError].Add(socket); + } + } + + int totalEvents = eventDict[SelectMode.SelectRead].Count + eventDict[SelectMode.SelectWrite].Count + eventDict[SelectMode.SelectError].Count; + // TODO: Maybe check all events first, wait for the timeout and then check the failed ones again? + int timeoutMicrosecondsPerEvent = timeout == -1 ? -1 : timeout / totalEvents; + + foreach ((SelectMode selectMode, List eventList) in eventDict) + { + List newEventList = []; + + foreach (ManagedProxySocket eventSocket in eventList) + { + if (eventSocket.Poll(timeoutMicrosecondsPerEvent, selectMode)) + { + newEventList.Add(eventSocket); + } + } + + eventDict[selectMode] = newEventList; + } + + updatedCount = eventDict[SelectMode.SelectRead].Count + eventDict[SelectMode.SelectWrite].Count + eventDict[SelectMode.SelectError].Count; + + foreach (PollEvent pollEvent in events) + { + ManagedProxySocket socket = (ManagedProxySocket)pollEvent.FileDescriptor; + + if (eventDict[SelectMode.SelectRead].Contains(socket)) + { + pollEvent.Data.OutputEvents |= PollEventTypeMask.Input; + } + + if (eventDict[SelectMode.SelectWrite].Contains(socket)) + { + pollEvent.Data.OutputEvents |= PollEventTypeMask.Output; + } + + if (eventDict[SelectMode.SelectError].Contains(socket)) + { + pollEvent.Data.OutputEvents |= PollEventTypeMask.Error; + } + } + + return LinuxError.SUCCESS; + } + } +} From eaf23843d4f920154f0475acbcbc33d63511554d Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:28:12 +0200 Subject: [PATCH 08/15] Update RyuSocks to v0.4.0-alpha --- Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 461388511b..422ca68257 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,7 +36,7 @@ - + @@ -50,4 +50,4 @@ - \ No newline at end of file + From f88c6122735c685565fbbf355058a3abddf5d0c9 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:34:04 +0200 Subject: [PATCH 09/15] Pass SocksClientStream to SslStream constructor for ManagedProxySocket This doesn't seem to work as expected yet. --- .../Ssl/SslService/SslManagedSocketConnection.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/SslManagedSocketConnection.cs b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/SslManagedSocketConnection.cs index 8cc761baf5..d9d06fe96b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/SslManagedSocketConnection.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/SslManagedSocketConnection.cs @@ -1,6 +1,7 @@ using Ryujinx.HLE.HOS.Services.Sockets.Bsd; using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl; using Ryujinx.HLE.HOS.Services.Ssl.Types; +using RyuSocks; using System; using System.IO; using System.Net; @@ -111,12 +112,25 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService { return hostName; } + // Thrown by ManagedProxySocket when accessing RemoteEndPoint before connecting to a remote. + catch (NullReferenceException) + { + return hostName; + } } public ResultCode Handshake(string hostName) { StartSslOperation(); - _stream = new SslStream(new NetworkStream(((ManagedSocket)Socket).Socket, false), false, null, null); + + Stream socketStream = Socket switch + { + ManagedSocket managedSocket => new NetworkStream(managedSocket.Socket, false), + ManagedProxySocket proxySocket => new SocksClientStream(proxySocket.ProxyClient, false), + _ => throw new NotSupportedException($"{typeof(Socket)} is not supported.") + }; + + _stream = new SslStream(socketStream, false, null, null); hostName = RetrieveHostName(hostName); _stream.AuthenticateAsClient(hostName, null, TranslateSslVersion(_sslVersion), false); EndSslOperation(); From 4b79de642784b1be50a613d6d534bc6686228624 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Fri, 6 Sep 2024 00:44:47 +0200 Subject: [PATCH 10/15] Update RyuSocks to v0.5.0-alpha --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 422ca68257..dfae7f5a15 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,7 +36,7 @@ - + From 9ac0393cea2d4d77a22498e9de3107e8e6b11682 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:43:34 +0200 Subject: [PATCH 11/15] ReceiveFrom: Copy proxyBuffer contents to buffer --- .../HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs index 73608c0308..90a9131f1f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs @@ -176,6 +176,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl receiveSize = ProxyClient.ReceiveFrom(proxyBuffer, WinSockHelper.ConvertBsdSocketFlags(flags), ref temp); + proxyBuffer[..receiveSize].CopyTo(buffer); + remoteEndPoint = (IPEndPoint)temp; result = LinuxError.SUCCESS; } From 44b81ba59e523e0091caeef887c698fff8650f86 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:44:13 +0200 Subject: [PATCH 12/15] Reset ProxyClient.RequestCommand --- .../HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs index 90a9131f1f..df66b83f29 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocket.cs @@ -450,6 +450,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl public void Disconnect() { ProxyClient.Disconnect(); + ProxyClient.RequestCommand = 0; } public LinuxError Shutdown(BsdSocketShutdownFlags how) @@ -469,6 +470,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl public void Close() { ProxyClient.Close(); + ProxyClient.RequestCommand = 0; } } } From 52736269d714f714f877f5d928158db312a60fa9 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:50:04 +0200 Subject: [PATCH 13/15] Make _proxyEndpoints thread-safe --- .../HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs index c5a0b5ed3a..db827500cc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/ProxyManager.cs @@ -1,4 +1,5 @@ using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Net; using System.Net.Sockets; @@ -8,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy { public static class ProxyManager { - private static readonly Dictionary _proxyEndpoints = new(); + private static readonly ConcurrentDictionary _proxyEndpoints = new(); [MethodImpl(MethodImplOptions.AggressiveInlining)] private static string GetKey(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) @@ -46,7 +47,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy public static bool Remove(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) { - return _proxyEndpoints.Remove(GetKey(addressFamily, socketType, protocolType)); + return _proxyEndpoints.Remove(GetKey(addressFamily, socketType, protocolType), out _); } } } From 940dda32b7cbd2c647694e6b806c094654e3fc0e Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:10:16 +0200 Subject: [PATCH 14/15] Update RyuSocks to v0.6.0-alpha --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index dfae7f5a15..65ca300f55 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,7 +36,7 @@ - + From eae65be6c268f3ecfbbf55875fa8532299bfbc21 Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:11:21 +0200 Subject: [PATCH 15/15] PollManager: Add Connected and IsBound check --- .../Sockets/Bsd/Impl/ManagedProxySocketPollManager.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocketPollManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocketPollManager.cs index fd7e730eea..02e6dad487 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocketPollManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedProxySocketPollManager.cs @@ -108,8 +108,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { outputEvents |= PollEventTypeMask.Error; - // TODO: Check ProxyClient.Connected and ProxyClient.IsBound when implemented. - // See ManagedSocketPollManager + if (!socket.ProxyClient.Connected || !socket.ProxyClient.IsBound) + { + outputEvents |= PollEventTypeMask.Disconnected; + } } if (eventDict[SelectMode.SelectRead].Contains(socket))