mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-12-18 17:02:02 +00:00
Add ManagedProxySocketPollManager impl
This commit is contained in:
parent
fe0c34c639
commit
f14df5cbb8
2 changed files with 212 additions and 0 deletions
|
@ -21,6 +21,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|||
{
|
||||
EventFileDescriptorPollManager.Instance,
|
||||
ManagedSocketPollManager.Instance,
|
||||
ManagedProxySocketPollManager.Instance,
|
||||
};
|
||||
|
||||
private BsdContext _context;
|
||||
|
|
|
@ -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<PollEvent> events, int timeoutMilliseconds, out int updatedCount)
|
||||
{
|
||||
Dictionary<SelectMode, List<ManagedProxySocket>> 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<ManagedProxySocket> eventList) in eventDict)
|
||||
{
|
||||
List<ManagedProxySocket> 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<PollEvent> events, int timeout, out int updatedCount)
|
||||
{
|
||||
Dictionary<SelectMode, List<ManagedProxySocket>> 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<ManagedProxySocket> eventList) in eventDict)
|
||||
{
|
||||
List<ManagedProxySocket> 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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue