mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-06-02 10:29:14 +00:00
TESTERS WANTED: RyuLDN implementation (#65)
These changes allow players to matchmake for local wireless using a LDN server. The network implementation originates from Berry's public TCP RyuLDN fork. Logo and unrelated changes have been removed. Additionally displays LDN game status in the game selection window when RyuLDN is enabled. Functionality is only enabled while network mode is set to "RyuLDN" in the settings.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy;
|
||||
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -21,21 +22,21 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
|
||||
public bool Blocking { get => Socket.Blocking; set => Socket.Blocking = value; }
|
||||
|
||||
public nint Handle => Socket.Handle;
|
||||
public nint Handle => IntPtr.Zero;
|
||||
|
||||
public IPEndPoint RemoteEndPoint => Socket.RemoteEndPoint as IPEndPoint;
|
||||
|
||||
public IPEndPoint LocalEndPoint => Socket.LocalEndPoint as IPEndPoint;
|
||||
|
||||
public Socket Socket { get; }
|
||||
public ISocketImpl Socket { get; }
|
||||
|
||||
public ManagedSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
|
||||
public ManagedSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, string lanInterfaceId)
|
||||
{
|
||||
Socket = new Socket(addressFamily, socketType, protocolType);
|
||||
Socket = SocketHelpers.CreateSocket(addressFamily, socketType, protocolType, lanInterfaceId);
|
||||
Refcount = 1;
|
||||
}
|
||||
|
||||
private ManagedSocket(Socket socket)
|
||||
private ManagedSocket(ISocketImpl socket)
|
||||
{
|
||||
Socket = socket;
|
||||
Refcount = 1;
|
||||
@@ -185,6 +186,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
}
|
||||
}
|
||||
|
||||
bool hasEmittedBlockingWarning = false;
|
||||
|
||||
public LinuxError Receive(out int receiveSize, Span<byte> buffer, BsdSocketFlags flags)
|
||||
{
|
||||
LinuxError result;
|
||||
@@ -199,6 +202,12 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
shouldBlockAfterOperation = true;
|
||||
}
|
||||
|
||||
if (Blocking && !hasEmittedBlockingWarning)
|
||||
{
|
||||
Logger.Warning?.PrintMsg(LogClass.ServiceBsd, "Blocking socket operations are not yet working properly. Expect network errors.");
|
||||
hasEmittedBlockingWarning = true;
|
||||
}
|
||||
|
||||
receiveSize = Socket.Receive(buffer, ConvertBsdSocketFlags(flags));
|
||||
|
||||
result = LinuxError.SUCCESS;
|
||||
@@ -236,6 +245,12 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
shouldBlockAfterOperation = true;
|
||||
}
|
||||
|
||||
if (Blocking && !hasEmittedBlockingWarning)
|
||||
{
|
||||
Logger.Warning?.PrintMsg(LogClass.ServiceBsd, "Blocking socket operations are not yet working properly. Expect network errors.");
|
||||
hasEmittedBlockingWarning = true;
|
||||
}
|
||||
|
||||
if (!Socket.IsBound)
|
||||
{
|
||||
receiveSize = -1;
|
||||
@@ -313,7 +328,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt Option: {option} Level: {level}");
|
||||
optionValue.Clear();
|
||||
|
||||
return LinuxError.SUCCESS;
|
||||
return LinuxError.EOPNOTSUPP;
|
||||
}
|
||||
|
||||
byte[] tempOptionValue = new byte[optionValue.Length];
|
||||
@@ -347,7 +362,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt Option: {option} Level: {level}");
|
||||
|
||||
return LinuxError.SUCCESS;
|
||||
return LinuxError.EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int value = optionValue.Length >= 4 ? MemoryMarshal.Read<int>(optionValue) : MemoryMarshal.Read<byte>(optionValue);
|
||||
@@ -493,7 +508,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
|
||||
try
|
||||
{
|
||||
int receiveSize = Socket.Receive(ConvertMessagesToBuffer(message), ConvertBsdSocketFlags(flags), out SocketError socketError);
|
||||
int receiveSize = (Socket as DefaultSocket).BaseSocket.Receive(ConvertMessagesToBuffer(message), ConvertBsdSocketFlags(flags), out SocketError socketError);
|
||||
|
||||
if (receiveSize > 0)
|
||||
{
|
||||
@@ -531,7 +546,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
|
||||
try
|
||||
{
|
||||
int sendSize = Socket.Send(ConvertMessagesToBuffer(message), ConvertBsdSocketFlags(flags), out SocketError socketError);
|
||||
int sendSize = (Socket as DefaultSocket).BaseSocket.Send(ConvertMessagesToBuffer(message), ConvertBsdSocketFlags(flags), out SocketError socketError);
|
||||
|
||||
if (sendSize > 0)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy;
|
||||
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
@@ -26,45 +27,46 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
|
||||
public LinuxError Poll(List<PollEvent> events, int timeoutMilliseconds, out int updatedCount)
|
||||
{
|
||||
List<Socket> readEvents = new();
|
||||
List<Socket> writeEvents = new();
|
||||
List<Socket> errorEvents = new();
|
||||
List<ISocketImpl> readEvents = new();
|
||||
List<ISocketImpl> writeEvents = new();
|
||||
List<ISocketImpl> errorEvents = new();
|
||||
|
||||
updatedCount = 0;
|
||||
|
||||
foreach (PollEvent evnt in events)
|
||||
{
|
||||
ManagedSocket socket = (ManagedSocket)evnt.FileDescriptor;
|
||||
|
||||
bool isValidEvent = evnt.Data.InputEvents == 0;
|
||||
|
||||
errorEvents.Add(socket.Socket);
|
||||
|
||||
if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0)
|
||||
if (evnt.FileDescriptor is ManagedSocket ms)
|
||||
{
|
||||
readEvents.Add(socket.Socket);
|
||||
bool isValidEvent = evnt.Data.InputEvents == 0;
|
||||
|
||||
isValidEvent = true;
|
||||
}
|
||||
errorEvents.Add(ms.Socket);
|
||||
|
||||
if ((evnt.Data.InputEvents & PollEventTypeMask.UrgentInput) != 0)
|
||||
{
|
||||
readEvents.Add(socket.Socket);
|
||||
if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0)
|
||||
{
|
||||
readEvents.Add(ms.Socket);
|
||||
|
||||
isValidEvent = true;
|
||||
}
|
||||
isValidEvent = true;
|
||||
}
|
||||
|
||||
if ((evnt.Data.InputEvents & PollEventTypeMask.Output) != 0)
|
||||
{
|
||||
writeEvents.Add(socket.Socket);
|
||||
if ((evnt.Data.InputEvents & PollEventTypeMask.UrgentInput) != 0)
|
||||
{
|
||||
readEvents.Add(ms.Socket);
|
||||
|
||||
isValidEvent = true;
|
||||
}
|
||||
isValidEvent = true;
|
||||
}
|
||||
|
||||
if (!isValidEvent)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Poll input event type: {evnt.Data.InputEvents}");
|
||||
return LinuxError.EINVAL;
|
||||
if ((evnt.Data.InputEvents & PollEventTypeMask.Output) != 0)
|
||||
{
|
||||
writeEvents.Add(ms.Socket);
|
||||
|
||||
isValidEvent = true;
|
||||
}
|
||||
|
||||
if (!isValidEvent)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Poll input event type: {evnt.Data.InputEvents}");
|
||||
return LinuxError.EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +74,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
{
|
||||
int actualTimeoutMicroseconds = timeoutMilliseconds == -1 ? -1 : timeoutMilliseconds * 1000;
|
||||
|
||||
Socket.Select(readEvents, writeEvents, errorEvents, actualTimeoutMicroseconds);
|
||||
SocketHelpers.Select(readEvents, writeEvents, errorEvents, actualTimeoutMicroseconds);
|
||||
}
|
||||
catch (SocketException exception)
|
||||
{
|
||||
@@ -81,34 +83,37 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
|
||||
foreach (PollEvent evnt in events)
|
||||
{
|
||||
Socket socket = ((ManagedSocket)evnt.FileDescriptor).Socket;
|
||||
|
||||
PollEventTypeMask outputEvents = evnt.Data.OutputEvents & ~evnt.Data.InputEvents;
|
||||
|
||||
if (errorEvents.Contains(socket))
|
||||
if (evnt.FileDescriptor is ManagedSocket ms)
|
||||
{
|
||||
outputEvents |= PollEventTypeMask.Error;
|
||||
ISocketImpl socket = ms.Socket;
|
||||
|
||||
if (!socket.Connected || !socket.IsBound)
|
||||
PollEventTypeMask outputEvents = evnt.Data.OutputEvents & ~evnt.Data.InputEvents;
|
||||
|
||||
if (errorEvents.Contains(ms.Socket))
|
||||
{
|
||||
outputEvents |= PollEventTypeMask.Disconnected;
|
||||
}
|
||||
}
|
||||
outputEvents |= PollEventTypeMask.Error;
|
||||
|
||||
if (readEvents.Contains(socket))
|
||||
{
|
||||
if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0)
|
||||
if (!socket.Connected || !socket.IsBound)
|
||||
{
|
||||
outputEvents |= PollEventTypeMask.Disconnected;
|
||||
}
|
||||
}
|
||||
|
||||
if (readEvents.Contains(ms.Socket))
|
||||
{
|
||||
outputEvents |= PollEventTypeMask.Input;
|
||||
if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0)
|
||||
{
|
||||
outputEvents |= PollEventTypeMask.Input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (writeEvents.Contains(socket))
|
||||
{
|
||||
outputEvents |= PollEventTypeMask.Output;
|
||||
}
|
||||
if (writeEvents.Contains(ms.Socket))
|
||||
{
|
||||
outputEvents |= PollEventTypeMask.Output;
|
||||
}
|
||||
|
||||
evnt.Data.OutputEvents = outputEvents;
|
||||
evnt.Data.OutputEvents = outputEvents;
|
||||
}
|
||||
}
|
||||
|
||||
updatedCount = readEvents.Count + writeEvents.Count + errorEvents.Count;
|
||||
@@ -118,53 +123,55 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
|
||||
public LinuxError Select(List<PollEvent> events, int timeout, out int updatedCount)
|
||||
{
|
||||
List<Socket> readEvents = new();
|
||||
List<Socket> writeEvents = new();
|
||||
List<Socket> errorEvents = new();
|
||||
List<ISocketImpl> readEvents = new();
|
||||
List<ISocketImpl> writeEvents = new();
|
||||
List<ISocketImpl> errorEvents = new();
|
||||
|
||||
updatedCount = 0;
|
||||
|
||||
foreach (PollEvent pollEvent in events)
|
||||
{
|
||||
ManagedSocket socket = (ManagedSocket)pollEvent.FileDescriptor;
|
||||
|
||||
if (pollEvent.Data.InputEvents.HasFlag(PollEventTypeMask.Input))
|
||||
if (pollEvent.FileDescriptor is ManagedSocket ms)
|
||||
{
|
||||
readEvents.Add(socket.Socket);
|
||||
}
|
||||
if (pollEvent.Data.InputEvents.HasFlag(PollEventTypeMask.Input))
|
||||
{
|
||||
readEvents.Add(ms.Socket);
|
||||
}
|
||||
|
||||
if (pollEvent.Data.InputEvents.HasFlag(PollEventTypeMask.Output))
|
||||
{
|
||||
writeEvents.Add(socket.Socket);
|
||||
}
|
||||
if (pollEvent.Data.InputEvents.HasFlag(PollEventTypeMask.Output))
|
||||
{
|
||||
writeEvents.Add(ms.Socket);
|
||||
}
|
||||
|
||||
if (pollEvent.Data.InputEvents.HasFlag(PollEventTypeMask.Error))
|
||||
{
|
||||
errorEvents.Add(socket.Socket);
|
||||
if (pollEvent.Data.InputEvents.HasFlag(PollEventTypeMask.Error))
|
||||
{
|
||||
errorEvents.Add(ms.Socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Socket.Select(readEvents, writeEvents, errorEvents, timeout);
|
||||
SocketHelpers.Select(readEvents, writeEvents, errorEvents, timeout);
|
||||
|
||||
updatedCount = readEvents.Count + writeEvents.Count + errorEvents.Count;
|
||||
|
||||
foreach (PollEvent pollEvent in events)
|
||||
{
|
||||
ManagedSocket socket = (ManagedSocket)pollEvent.FileDescriptor;
|
||||
|
||||
if (readEvents.Contains(socket.Socket))
|
||||
if (pollEvent.FileDescriptor is ManagedSocket ms)
|
||||
{
|
||||
pollEvent.Data.OutputEvents |= PollEventTypeMask.Input;
|
||||
}
|
||||
if (readEvents.Contains(ms.Socket))
|
||||
{
|
||||
pollEvent.Data.OutputEvents |= PollEventTypeMask.Input;
|
||||
}
|
||||
|
||||
if (writeEvents.Contains(socket.Socket))
|
||||
{
|
||||
pollEvent.Data.OutputEvents |= PollEventTypeMask.Output;
|
||||
}
|
||||
if (writeEvents.Contains(ms.Socket))
|
||||
{
|
||||
pollEvent.Data.OutputEvents |= PollEventTypeMask.Output;
|
||||
}
|
||||
|
||||
if (errorEvents.Contains(socket.Socket))
|
||||
{
|
||||
pollEvent.Data.OutputEvents |= PollEventTypeMask.Error;
|
||||
if (errorEvents.Contains(ms.Socket))
|
||||
{
|
||||
pollEvent.Data.OutputEvents |= PollEventTypeMask.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user