forked from emmauss/Ryujinx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bsd: Revamp API and make socket abstract (#2960)
* 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
Showing
21 changed files
with
1,471 additions
and
648 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
Oops, something went wrong.