Fix GetAddrInfoWithOptions and some sockets issues (#2936)
* Fix GetAddrInfoWithOptions and some sockets issues * Was not supposed to remove this log
This commit is contained in:
parent
c0056546e7
commit
0b1185284c
14 changed files with 237 additions and 108 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue