Skip to content

Commit

Permalink
bsd: Revamp API and make socket abstract (#2960)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Mary authored Jan 12, 2022
1 parent d300a5a commit 366fe2d
Show file tree
Hide file tree
Showing 21 changed files with 1,471 additions and 648 deletions.
150 changes: 150 additions & 0 deletions Ryujinx.HLE/HOS/Services/Sockets/Bsd/BsdContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
{
class BsdContext
{
private static ConcurrentDictionary<long, BsdContext> _registry = new ConcurrentDictionary<long, BsdContext>();

private readonly object _lock = new object();

private List<IFileDescriptor> _fds;

private BsdContext()
{
_fds = new List<IFileDescriptor>();
}

public ISocket RetrieveSocket(int socketFd)
{
IFileDescriptor file = RetrieveFileDescriptor(socketFd);

if (file is ISocket socket)
{
return socket;
}

return null;
}

public IFileDescriptor RetrieveFileDescriptor(int fd)
{
lock (_lock)
{
if (fd >= 0 && _fds.Count > fd)
{
return _fds[fd];
}
}

return null;
}

public int RegisterFileDescriptor(IFileDescriptor file)
{
lock (_lock)
{
for (int fd = 0; fd < _fds.Count; fd++)
{
if (_fds[fd] == null)
{
_fds[fd] = file;

return fd;
}
}

_fds.Add(file);

return _fds.Count - 1;
}
}

public int DuplicateFileDescriptor(int fd)
{
IFileDescriptor oldFile = RetrieveFileDescriptor(fd);

if (oldFile != null)
{
lock (_lock)
{
oldFile.Refcount++;

return RegisterFileDescriptor(oldFile);
}
}

return -1;
}

public bool CloseFileDescriptor(int fd)
{
IFileDescriptor file = RetrieveFileDescriptor(fd);

if (file != null)
{
file.Refcount--;

if (file.Refcount <= 0)
{
file.Dispose();
}

lock (_lock)
{
_fds[fd] = null;
}

return true;
}

return false;
}

public LinuxError ShutdownAllSockets(BsdSocketShutdownFlags how)
{
lock (_lock)
{
foreach (IFileDescriptor file in _fds)
{
if (file is ISocket socket)
{
LinuxError errno = socket.Shutdown(how);

if (errno != LinuxError.SUCCESS)
{
return errno;
}
}
}
}

return LinuxError.SUCCESS;
}

public static BsdContext GetOrRegister(long processId)
{
BsdContext context = GetContext(processId);

if (context == null)
{
context = new BsdContext();

_registry.TryAdd(processId, context);
}

return context;
}

public static BsdContext GetContext(long processId)
{
if (!_registry.TryGetValue(processId, out BsdContext processContext))
{
return null;
}

return processContext;
}
}
}
Loading

0 comments on commit 366fe2d

Please sign in to comment.