mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-12-23 17:56:01 +00:00
366fe2dbb2
* bsd: Revamp API and make socket abstract This part of the code was really ancient and needed some love. As such this commit aims at separating the socket core logic from the IClient class and make it uses more modern APIs to read/write/parse data. * Address gdkchan's comment * Move TryConvertSocketOption to WinSockHelper * Allow reusing old fds and add missing locks around SocketInternal and ShutdownAllSockets * bsd: ton of changes - Make sockets per process - Implement eventfds - Rework Poll for support of eventfds - Handle protocol auto selection by type (used by gRPC) - Handle IPv6 socket creation * Address most of gdkchan comments * Fix inverted read logic for BSD socket read * bsd: Make Poll abstract via IBsdSocketPollManager * bsd: Improve naming of everything * Fix build issue from last commit (missed to save on VC) * Switch BsdContext registry to a concurrent dictionary * bsd: Implement socket creation flags logic and the non blocking flag * Remove unused enum from previous commit * bsd: Fix poll logic when 0 fds are present for a given poll manager and when timeout is very small (or 0) * Address gdkchan's comment
129 lines
3.9 KiB
C#
129 lines
3.9 KiB
C#
using Ryujinx.Common.Logging;
|
|
using System.Collections.Generic;
|
|
using System.Net.Sockets;
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|
{
|
|
class ManagedSocketPollManager : IPollManager
|
|
{
|
|
private static ManagedSocketPollManager _instance;
|
|
|
|
public static ManagedSocketPollManager Instance
|
|
{
|
|
get
|
|
{
|
|
if (_instance == null)
|
|
{
|
|
_instance = new ManagedSocketPollManager();
|
|
}
|
|
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
public bool IsCompatible(PollEvent evnt)
|
|
{
|
|
return evnt.FileDescriptor is ManagedSocket;
|
|
}
|
|
|
|
public LinuxError Poll(List<PollEvent> events, int timeoutMilliseconds, out int updatedCount)
|
|
{
|
|
List<Socket> readEvents = new List<Socket>();
|
|
List<Socket> writeEvents = new List<Socket>();
|
|
List<Socket> errorEvents = new List<Socket>();
|
|
|
|
updatedCount = 0;
|
|
|
|
foreach (PollEvent evnt in events)
|
|
{
|
|
ManagedSocket socket = (ManagedSocket)evnt.FileDescriptor;
|
|
|
|
bool isValidEvent = false;
|
|
|
|
if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0)
|
|
{
|
|
readEvents.Add(socket.Socket);
|
|
errorEvents.Add(socket.Socket);
|
|
|
|
isValidEvent = true;
|
|
}
|
|
|
|
if ((evnt.Data.InputEvents & PollEventTypeMask.UrgentInput) != 0)
|
|
{
|
|
readEvents.Add(socket.Socket);
|
|
errorEvents.Add(socket.Socket);
|
|
|
|
isValidEvent = true;
|
|
}
|
|
|
|
if ((evnt.Data.InputEvents & PollEventTypeMask.Output) != 0)
|
|
{
|
|
writeEvents.Add(socket.Socket);
|
|
errorEvents.Add(socket.Socket);
|
|
|
|
isValidEvent = true;
|
|
}
|
|
|
|
if ((evnt.Data.InputEvents & PollEventTypeMask.Error) != 0)
|
|
{
|
|
errorEvents.Add(socket.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;
|
|
|
|
Socket.Select(readEvents, writeEvents, errorEvents, actualTimeoutMicroseconds);
|
|
}
|
|
catch (SocketException exception)
|
|
{
|
|
return WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
|
|
}
|
|
|
|
foreach (PollEvent evnt in events)
|
|
{
|
|
Socket socket = ((ManagedSocket)evnt.FileDescriptor).Socket;
|
|
|
|
PollEventTypeMask outputEvents = 0;
|
|
|
|
if (errorEvents.Contains(socket))
|
|
{
|
|
outputEvents |= PollEventTypeMask.Error;
|
|
|
|
if (!socket.Connected || !socket.IsBound)
|
|
{
|
|
outputEvents |= PollEventTypeMask.Disconnected;
|
|
}
|
|
}
|
|
|
|
if (readEvents.Contains(socket))
|
|
{
|
|
if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0)
|
|
{
|
|
outputEvents |= PollEventTypeMask.Input;
|
|
}
|
|
}
|
|
|
|
if (writeEvents.Contains(socket))
|
|
{
|
|
outputEvents |= PollEventTypeMask.Output;
|
|
}
|
|
|
|
evnt.Data.OutputEvents = outputEvents;
|
|
}
|
|
|
|
updatedCount = readEvents.Count + writeEvents.Count + errorEvents.Count;
|
|
|
|
return LinuxError.SUCCESS;
|
|
}
|
|
}
|
|
}
|