diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2021-12-26 11:17:13 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-26 15:17:13 +0100 |
| commit | 0b1185284c311510d08eb4a3442823356a785e24 (patch) | |
| tree | ce86ea85c6c1ede4d5553da3a5f1bcdeb2835728 /Ryujinx.HLE/HOS | |
| parent | c0056546e72b148ccc561eba7b8daa6a78f484ae (diff) | |
Fix GetAddrInfoWithOptions and some sockets issues (#2936)
* Fix GetAddrInfoWithOptions and some sockets issues
* Was not supposed to remove this log
Diffstat (limited to 'Ryujinx.HLE/HOS')
5 files changed, 161 insertions, 90 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs b/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs index a1c40aeb..7a3fdabd 100644 --- a/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs +++ b/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs @@ -8,6 +8,13 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService { class IRequest : IpcService { + private enum RequestState + { + Error = 1, + OnHold = 2, + Available = 3 + } + private KEvent _event0; private KEvent _event1; @@ -28,7 +35,11 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService // GetRequestState() -> u32 public ResultCode GetRequestState(ServiceCtx context) { - context.ResponseData.Write(1); + RequestState requestState = context.Device.Configuration.EnableInternetAccess + ? RequestState.Available + : RequestState.Error; + + context.ResponseData.Write((int)requestState); Logger.Stub?.PrintStub(LogClass.ServiceNifm); diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs index 355ef864..43c7ee7d 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs @@ -106,7 +106,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd _isPrivileged = isPrivileged; } - private LinuxError ConvertError(WsaError errorCode) + private static LinuxError ConvertError(WsaError errorCode) { if (!_errorMap.TryGetValue(errorCode, out LinuxError errno)) { @@ -116,6 +116,56 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd return errno; } + private static SocketFlags ConvertBsdSocketFlags(BsdSocketFlags bsdSocketFlags) + { + BsdSocketFlags SupportedFlags = + BsdSocketFlags.Oob | + BsdSocketFlags.Peek | + BsdSocketFlags.DontRoute | + BsdSocketFlags.Trunc | + BsdSocketFlags.CTrunc; + + 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.Trunc | + BsdSocketFlags.CTrunc); + + if (bsdSocketFlags != BsdSocketFlags.None) + { + Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported socket flags: {bsdSocketFlags}"); + } + + return socketFlags; + } + private ResultCode WriteWinSock2Error(ServiceCtx context, WsaError errorCode) { return WriteBsdResult(context, -1, ConvertError(errorCode)); @@ -463,8 +513,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd // Recv(u32 socket, u32 flags) -> (i32 ret, u32 bsd_errno, array<i8, 0x22> message) public ResultCode Recv(ServiceCtx context) { - int socketFd = context.RequestData.ReadInt32(); - SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32(); + int socketFd = context.RequestData.ReadInt32(); + BsdSocketFlags socketFlags = (BsdSocketFlags)context.RequestData.ReadInt32(); (ulong receivePosition, ulong receiveLength) = context.Request.GetBufferType0x22(); @@ -474,18 +524,11 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd if (socket != null) { - if (socketFlags != SocketFlags.None && (socketFlags & SocketFlags.OutOfBand) == 0 - && (socketFlags & SocketFlags.Peek) == 0) - { - Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Recv flags: {socketFlags}"); - return WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP); - } - byte[] receivedBuffer = new byte[receiveLength]; try { - result = socket.Handle.Receive(receivedBuffer, socketFlags); + result = socket.Handle.Receive(receivedBuffer, ConvertBsdSocketFlags(socketFlags)); errno = SetResultErrno(socket.Handle, result); context.Memory.Write(receivePosition, receivedBuffer); @@ -503,8 +546,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd // RecvFrom(u32 sock, u32 flags) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<i8, 0x22, 0> message, buffer<nn::socket::sockaddr_in, 0x22, 0x10>) public ResultCode RecvFrom(ServiceCtx context) { - int socketFd = context.RequestData.ReadInt32(); - SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32(); + int socketFd = context.RequestData.ReadInt32(); + BsdSocketFlags socketFlags = (BsdSocketFlags)context.RequestData.ReadInt32(); (ulong receivePosition, ulong receiveLength) = context.Request.GetBufferType0x22(); (ulong sockAddrOutPosition, ulong sockAddrOutSize) = context.Request.GetBufferType0x22(1); @@ -515,20 +558,12 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd if (socket != null) { - if (socketFlags != SocketFlags.None && (socketFlags & SocketFlags.OutOfBand) == 0 - && (socketFlags & SocketFlags.Peek) == 0) - { - Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Recv flags: {socketFlags}"); - - return WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP); - } - byte[] receivedBuffer = new byte[receiveLength]; EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0); try { - result = socket.Handle.ReceiveFrom(receivedBuffer, receivedBuffer.Length, socketFlags, ref endPoint); + result = socket.Handle.ReceiveFrom(receivedBuffer, receivedBuffer.Length, ConvertBsdSocketFlags(socketFlags), ref endPoint); errno = SetResultErrno(socket.Handle, result); context.Memory.Write(receivePosition, receivedBuffer); @@ -547,8 +582,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd // Send(u32 socket, u32 flags, buffer<i8, 0x21, 0>) -> (i32 ret, u32 bsd_errno) public ResultCode Send(ServiceCtx context) { - int socketFd = context.RequestData.ReadInt32(); - SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32(); + int socketFd = context.RequestData.ReadInt32(); + BsdSocketFlags socketFlags = (BsdSocketFlags)context.RequestData.ReadInt32(); (ulong sendPosition, ulong sendSize) = context.Request.GetBufferType0x21(); @@ -558,21 +593,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd if (socket != null) { - if (socketFlags != SocketFlags.None && socketFlags != SocketFlags.OutOfBand - && socketFlags != SocketFlags.Peek && socketFlags != SocketFlags.DontRoute) - { - Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Send flags: {socketFlags}"); - - return WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP); - } - byte[] sendBuffer = new byte[sendSize]; context.Memory.Read(sendPosition, sendBuffer); try { - result = socket.Handle.Send(sendBuffer, socketFlags); + result = socket.Handle.Send(sendBuffer, ConvertBsdSocketFlags(socketFlags)); errno = SetResultErrno(socket.Handle, result); } catch (SocketException exception) @@ -589,8 +616,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd // SendTo(u32 socket, u32 flags, buffer<i8, 0x21, 0>, buffer<nn::socket::sockaddr_in, 0x21, 0x10>) -> (i32 ret, u32 bsd_errno) public ResultCode SendTo(ServiceCtx context) { - int socketFd = context.RequestData.ReadInt32(); - SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32(); + int socketFd = context.RequestData.ReadInt32(); + BsdSocketFlags socketFlags = (BsdSocketFlags)context.RequestData.ReadInt32(); (ulong sendPosition, ulong sendSize) = context.Request.GetBufferType0x21(); (ulong bufferPosition, ulong bufferSize) = context.Request.GetBufferType0x21(1); @@ -601,14 +628,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd if (socket != null) { - if (socketFlags != SocketFlags.None && socketFlags != SocketFlags.OutOfBand - && socketFlags != SocketFlags.Peek && socketFlags != SocketFlags.DontRoute) - { - Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Send flags: {socketFlags}"); - - return WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP); - } - byte[] sendBuffer = new byte[sendSize]; context.Memory.Read(sendPosition, sendBuffer); @@ -617,7 +636,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd try { - result = socket.Handle.SendTo(sendBuffer, sendBuffer.Length, socketFlags, endPoint); + result = socket.Handle.SendTo(sendBuffer, sendBuffer.Length, ConvertBsdSocketFlags(socketFlags), endPoint); errno = SetResultErrno(socket.Handle, result); } catch (SocketException exception) @@ -737,7 +756,14 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd } catch (SocketException exception) { - errno = ConvertError((WsaError)exception.ErrorCode); + if (!socket.Handle.Blocking && exception.ErrorCode == (int)WsaError.WSAEWOULDBLOCK) + { + errno = LinuxError.EINPROGRESS; + } + else + { + errno = ConvertError((WsaError)exception.ErrorCode); + } } } @@ -794,9 +820,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd // GetSockOpt(u32 socket, u32 level, u32 option_name) -> (i32 ret, u32 bsd_errno, u32, buffer<unknown, 0x22, 0>) public ResultCode GetSockOpt(ServiceCtx context) { - int socketFd = context.RequestData.ReadInt32(); - int level = context.RequestData.ReadInt32(); - int optionName = context.RequestData.ReadInt32(); + int socketFd = context.RequestData.ReadInt32(); + SocketOptionLevel level = (SocketOptionLevel)context.RequestData.ReadInt32(); + SocketOptionName optionName = (SocketOptionName)context.RequestData.ReadInt32(); (ulong bufferPosition, ulong bufferSize) = context.Request.GetBufferType0x22(); @@ -805,16 +831,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd if (socket != null) { - errno = LinuxError.ENOPROTOOPT; - - if (level == 0xFFFF) - { - errno = HandleGetSocketOption(context, socket, (SocketOptionName)optionName, bufferPosition, bufferSize); - } - else - { - Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt Level: {(SocketOptionLevel)level}"); - } + errno = HandleGetSocketOption(context, socket, optionName, level, bufferPosition, bufferSize); } return WriteBsdResult(context, 0, errno); @@ -916,7 +933,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd return WriteBsdResult(context, result, errno); } - private LinuxError HandleGetSocketOption(ServiceCtx context, BsdSocket socket, SocketOptionName optionName, ulong optionValuePosition, ulong optionValueSize) + private static LinuxError HandleGetSocketOption( + ServiceCtx context, + BsdSocket socket, + SocketOptionName optionName, + SocketOptionLevel level, + ulong optionValuePosition, + ulong optionValueSize) { try { @@ -936,19 +959,19 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd case SocketOptionName.SendTimeout: case SocketOptionName.Type: case SocketOptionName.Linger: - socket.Handle.GetSocketOption(SocketOptionLevel.Socket, optionName, optionValue); + socket.Handle.GetSocketOption(level, optionName, optionValue); context.Memory.Write(optionValuePosition, optionValue); return LinuxError.SUCCESS; case (SocketOptionName)0x200: - socket.Handle.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue); + socket.Handle.GetSocketOption(level, SocketOptionName.ReuseAddress, optionValue); context.Memory.Write(optionValuePosition, optionValue); return LinuxError.SUCCESS; default: - Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt OptionName: {optionName}"); + Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt OptionName: {optionName}"); return LinuxError.EOPNOTSUPP; } @@ -959,7 +982,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd } } - private LinuxError HandleSetSocketOption(ServiceCtx context, BsdSocket socket, SocketOptionName optionName, ulong optionValuePosition, ulong optionValueSize) + private static LinuxError HandleSetSocketOption( + ServiceCtx context, + BsdSocket socket, + SocketOptionName optionName, + SocketOptionLevel level, + ulong optionValuePosition, + ulong optionValueSize) { try { @@ -977,17 +1006,17 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd case SocketOptionName.SendTimeout: case SocketOptionName.Type: case SocketOptionName.ReuseAddress: - socket.Handle.SetSocketOption(SocketOptionLevel.Socket, optionName, context.Memory.Read<int>((ulong)optionValuePosition)); + socket.Handle.SetSocketOption(level, optionName, context.Memory.Read<int>((ulong)optionValuePosition)); return LinuxError.SUCCESS; case (SocketOptionName)0x200: - socket.Handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, context.Memory.Read<int>((ulong)optionValuePosition)); + socket.Handle.SetSocketOption(level, SocketOptionName.ReuseAddress, context.Memory.Read<int>((ulong)optionValuePosition)); return LinuxError.SUCCESS; case SocketOptionName.Linger: - socket.Handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, + socket.Handle.SetSocketOption(level, SocketOptionName.Linger, new LingerOption(context.Memory.Read<int>((ulong)optionValuePosition) != 0, context.Memory.Read<int>((ulong)optionValuePosition + 4))); return LinuxError.SUCCESS; @@ -1008,9 +1037,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd // SetSockOpt(u32 socket, u32 level, u32 option_name, buffer<unknown, 0x21, 0> option_value) -> (i32 ret, u32 bsd_errno) public ResultCode SetSockOpt(ServiceCtx context) { - int socketFd = context.RequestData.ReadInt32(); - int level = context.RequestData.ReadInt32(); - int optionName = context.RequestData.ReadInt32(); + int socketFd = context.RequestData.ReadInt32(); + SocketOptionLevel level = (SocketOptionLevel)context.RequestData.ReadInt32(); + SocketOptionName optionName = (SocketOptionName)context.RequestData.ReadInt32(); (ulong bufferPos, ulong bufferSize) = context.Request.GetBufferType0x21(); @@ -1019,16 +1048,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd if (socket != null) { - errno = LinuxError.ENOPROTOOPT; - - if (level == 0xFFFF) - { - errno = HandleSetSocketOption(context, socket, (SocketOptionName)optionName, bufferPos, bufferSize); - } - else - { - Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt Level: {(SocketOptionLevel)level}"); - } + errno = HandleSetSocketOption(context, socket, optionName, level, bufferPos, bufferSize); } return WriteBsdResult(context, 0, errno); diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketFlags.cs b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketFlags.cs new file mode 100644 index 00000000..4dc56356 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketFlags.cs @@ -0,0 +1,24 @@ +using System.Net.Sockets; + +namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd +{ + enum BsdSocketFlags + { + None = 0, + Oob = 0x1, + Peek = 0x2, + DontRoute = 0x4, + Eor = 0x8, + Trunc = 0x10, + CTrunc = 0x20, + WaitAll = 0x40, + DontWait = 0x80, + Eof = 0x100, + Notification = 0x2000, + Nbio = 0x4000, + Compat = 0x8000, + SoCallbck = 0x10000, + NoSignal = 0x20000, + CMsgCloExec = 0x40000 + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs b/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs index 06df4d13..f5ae3818 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs @@ -155,7 +155,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres ulong responseBufferPosition = context.Request.ReceiveBuff[0].Position; ulong responseBufferSize = context.Request.ReceiveBuff[0].Size; - return GetAddrInfoRequestImpl(context, responseBufferPosition, responseBufferSize, 0, 0); + return GetAddrInfoRequestImpl(context, responseBufferPosition, responseBufferSize, false, 0, 0); } [CommandHipc(8)] @@ -213,7 +213,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres (ulong responseBufferPosition, ulong responseBufferSize) = context.Request.GetBufferType0x22(); (ulong optionsBufferPosition, ulong optionsBufferSize) = context.Request.GetBufferType0x21(); - return GetAddrInfoRequestImpl(context, responseBufferPosition, responseBufferSize, optionsBufferPosition, optionsBufferSize); + return GetAddrInfoRequestImpl(context, responseBufferPosition, responseBufferSize, true, optionsBufferPosition, optionsBufferSize); } private ResultCode GetHostByNameRequestImpl(ServiceCtx context, ulong inputBufferPosition, ulong inputBufferSize, ulong outputBufferPosition, ulong outputBufferSize, ulong optionsBufferPosition, ulong optionsBufferSize) @@ -391,7 +391,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres return bufferPosition - originalBufferPosition; } - private ResultCode GetAddrInfoRequestImpl(ServiceCtx context, ulong responseBufferPosition, ulong responseBufferSize, ulong optionsBufferPosition, ulong optionsBufferSize) + private ResultCode GetAddrInfoRequestImpl( + ServiceCtx context, + ulong responseBufferPosition, + ulong responseBufferSize, + bool withOptions, + ulong optionsBufferPosition, + ulong optionsBufferSize) { bool enableNsdResolve = (context.RequestData.ReadInt32() & 1) != 0; uint cancelHandle = context.RequestData.ReadUInt32(); @@ -402,7 +408,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres // NOTE: We ignore hints for now. DeserializeAddrInfos(context.Memory, (ulong)context.Request.SendBuff[2].Position, (ulong)context.Request.SendBuff[2].Size); - if (optionsBufferSize > 0) + if (withOptions) { // TODO: Find unknown, Parse and use options. uint unknown = context.RequestData.ReadUInt32(); @@ -457,9 +463,19 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres serializedSize = SerializeAddrInfos(context, responseBufferPosition, responseBufferSize, hostEntry, port); } - context.ResponseData.Write((int)netDbErrorCode); - context.ResponseData.Write((int)errno); - context.ResponseData.Write(serializedSize); + if (withOptions) + { + context.ResponseData.Write(serializedSize); + context.ResponseData.Write((int)errno); + context.ResponseData.Write((int)netDbErrorCode); + context.ResponseData.Write(0); + } + else + { + context.ResponseData.Write((int)netDbErrorCode); + context.ResponseData.Write((int)errno); + context.ResponseData.Write(serializedSize); + } return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/Types/AddrInfo4.cs b/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/Types/AddrInfo4.cs index 515d8649..0e1d3aae 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/Types/AddrInfo4.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/Types/AddrInfo4.cs @@ -21,9 +21,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types Port = port; Address = default; - address.GetAddressBytes().AsSpan().CopyTo(Address.ToSpan()); - - Address.ToSpan().Reverse(); + Span<byte> outAddress = Address.ToSpan(); + address.TryWriteBytes(outAddress, out _); + outAddress.Reverse(); } } }
\ No newline at end of file |
