Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TESTERS WANTED: RyuLDN implementation #65

Merged
merged 16 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<PackageVersion Include="OpenTK.Graphics" Version="4.8.2" />
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace Ryujinx.Common.Configuration.Multiplayer
public enum MultiplayerMode
{
Disabled,
LdnRyu,
LdnMitm,
}
}
18 changes: 9 additions & 9 deletions src/Ryujinx.Common/Memory/StructArrayHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -803,25 +803,25 @@ public struct Array128<T> : IArray<T> where T : unmanaged
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
}

public struct Array256<T> : IArray<T> where T : unmanaged
public struct Array140<T> : IArray<T> where T : unmanaged
{
T _e0;
Array128<T> _other;
Array127<T> _other2;
public readonly int Length => 256;
Array64<T> _other;
Array64<T> _other2;
Array11<T> _other3;
public readonly int Length => 140;
public ref T this[int index] => ref AsSpan()[index];

[Pure]
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
}

public struct Array140<T> : IArray<T> where T : unmanaged
public struct Array256<T> : IArray<T> where T : unmanaged
{
T _e0;
Array64<T> _other;
Array64<T> _other2;
Array11<T> _other3;
public readonly int Length => 140;
Array128<T> _other;
Array127<T> _other2;
public readonly int Length => 256;
public ref T this[int index] => ref AsSpan()[index];

[Pure]
Expand Down
6 changes: 6 additions & 0 deletions src/Ryujinx.Common/Utilities/NetworkHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Buffers.Binary;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;

namespace Ryujinx.Common.Utilities
{
Expand Down Expand Up @@ -65,6 +66,11 @@ public static (IPInterfaceProperties, UnicastIPAddressInformation) GetLocalInter
return (targetProperties, targetAddressInfo);
}

public static bool SupportsDynamicDns()
{
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
}

public static uint ConvertIpv4Address(IPAddress ipAddress)
{
return BinaryPrimitives.ReadUInt32BigEndian(ipAddress.GetAddressBytes());
Expand Down
2 changes: 1 addition & 1 deletion src/Ryujinx.Graphics.GAL/IRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public interface IRenderer : IDisposable
IPipeline Pipeline { get; }

IWindow Window { get; }

uint ProgramCount { get; }

void BackgroundContextAction(Action action, bool alwaysBackground = false);
Expand Down
2 changes: 1 addition & 1 deletion src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public IImageArray CreateImageArray(int size, bool isBuffer)
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
{
ProgramCount++;

return new Program(shaders, info.FragmentOutputMap);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ public IImageArray CreateImageArray(int size, bool isBuffer)
public IProgram CreateProgram(ShaderSource[] sources, ShaderInfo info)
{
ProgramCount++;

bool isCompute = sources.Length == 1 && sources[0].Stage == ShaderStage.Compute;

if (info.State.HasValue || isCompute)
Expand Down
16 changes: 15 additions & 1 deletion src/Ryujinx.HLE/HLEConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,16 @@ public class HLEConfiguration
/// </summary>
public MultiplayerMode MultiplayerMode { internal get; set; }

/// <summary>
/// Disable P2P mode
/// </summary>
public bool MultiplayerDisableP2p { internal get; set; }

/// <summary>
/// Multiplayer Passphrase
/// </summary>
public string MultiplayerLdnPassphrase { internal get; set; }

/// <summary>
/// An action called when HLE force a refresh of output after docked mode changed.
/// </summary>
Expand Down Expand Up @@ -194,7 +204,9 @@ public HLEConfiguration(VirtualFileSystem virtualFileSystem,
float audioVolume,
bool useHypervisor,
string multiplayerLanInterfaceId,
MultiplayerMode multiplayerMode)
MultiplayerMode multiplayerMode,
bool multiplayerDisableP2p,
string multiplayerLdnPassphrase)
{
VirtualFileSystem = virtualFileSystem;
LibHacHorizonManager = libHacHorizonManager;
Expand Down Expand Up @@ -222,6 +234,8 @@ public HLEConfiguration(VirtualFileSystem virtualFileSystem,
UseHypervisor = useHypervisor;
MultiplayerLanInterfaceId = multiplayerLanInterfaceId;
MultiplayerMode = multiplayerMode;
MultiplayerDisableP2p = multiplayerDisableP2p;
MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
}
}
}
2 changes: 1 addition & 1 deletion src/Ryujinx.HLE/HOS/Services/Ldn/Types/NetworkConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Ryujinx.HLE.HOS.Services.Ldn.Types
{
[StructLayout(LayoutKind.Sequential, Size = 0x20)]
[StructLayout(LayoutKind.Sequential, Size = 0x20, Pack = 8)]
struct NetworkConfig
{
public IntentId IntentId;
Expand Down
2 changes: 1 addition & 1 deletion src/Ryujinx.HLE/HOS/Services/Ldn/Types/ScanFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Ryujinx.HLE.HOS.Services.Ldn.Types
{
[StructLayout(LayoutKind.Sequential, Size = 0x60)]
[StructLayout(LayoutKind.Sequential, Size = 0x60, Pack = 8)]
struct ScanFilter
{
public NetworkId NetworkId;
Expand Down
2 changes: 1 addition & 1 deletion src/Ryujinx.HLE/HOS/Services/Ldn/Types/SecurityConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Ryujinx.HLE.HOS.Services.Ldn.Types
{
[StructLayout(LayoutKind.Sequential, Size = 0x44)]
[StructLayout(LayoutKind.Sequential, Size = 0x44, Pack = 2)]
struct SecurityConfig
{
public SecurityMode SecurityMode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Ryujinx.HLE.HOS.Services.Ldn.Types
{
[StructLayout(LayoutKind.Sequential, Size = 0x20)]
[StructLayout(LayoutKind.Sequential, Size = 0x20, Pack = 1)]
struct SecurityParameter
{
public Array16<byte> Data;
Expand Down
2 changes: 1 addition & 1 deletion src/Ryujinx.HLE/HOS/Services/Ldn/Types/UserConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Ryujinx.HLE.HOS.Services.Ldn.Types
{
[StructLayout(LayoutKind.Sequential, Size = 0x30)]
[StructLayout(LayoutKind.Sequential, Size = 0x30, Pack = 1)]
struct UserConfig
{
public Array33<byte> UserName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class AccessPoint : IDisposable
public Array8<NodeLatestUpdate> LatestUpdates = new();
public bool Connected { get; private set; }

public ProxyConfig Config => _parent.NetworkClient.Config;

public AccessPoint(IUserLocalCommunicationService parent)
{
_parent = parent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
{
interface INetworkClient : IDisposable
{
ProxyConfig Config { get; }
bool NeedsRealId { get; }

event EventHandler<NetworkChangeEventArgs> NetworkChange;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.HOS.Services.Ldn.Types;
using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm;
using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu;
using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.Types;
using Ryujinx.Horizon.Common;
using Ryujinx.Memory;
using System;
Expand All @@ -21,6 +23,9 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
{
class IUserLocalCommunicationService : IpcService, IDisposable
{
public static string LanPlayHost = "ryuldn.vudjun.com";
Vudjun marked this conversation as resolved.
Show resolved Hide resolved
public static short LanPlayPort = 30456;

public INetworkClient NetworkClient { get; private set; }

private const int NifmRequestID = 90;
Expand Down Expand Up @@ -175,19 +180,37 @@ public ResultCode GetIpv4Address(ServiceCtx context)

if (_state == NetworkState.AccessPointCreated || _state == NetworkState.StationConnected)
{
(_, UnicastIPAddressInformation unicastAddress) = NetworkHelpers.GetLocalInterface(context.Device.Configuration.MultiplayerLanInterfaceId);
ProxyConfig config = _state switch
{
NetworkState.AccessPointCreated => _accessPoint.Config,
NetworkState.StationConnected => _station.Config,

if (unicastAddress == null)
_ => default
};

if (config.ProxyIp == 0)
{
context.ResponseData.Write(NetworkHelpers.ConvertIpv4Address(DefaultIPAddress));
context.ResponseData.Write(NetworkHelpers.ConvertIpv4Address(DefaultSubnetMask));
(_, UnicastIPAddressInformation unicastAddress) = NetworkHelpers.GetLocalInterface(context.Device.Configuration.MultiplayerLanInterfaceId);

if (unicastAddress == null)
{
context.ResponseData.Write(NetworkHelpers.ConvertIpv4Address(DefaultIPAddress));
context.ResponseData.Write(NetworkHelpers.ConvertIpv4Address(DefaultSubnetMask));
}
else
{
Logger.Info?.Print(LogClass.ServiceLdn, $"Console's LDN IP is \"{unicastAddress.Address}\".");

context.ResponseData.Write(NetworkHelpers.ConvertIpv4Address(unicastAddress.Address));
context.ResponseData.Write(NetworkHelpers.ConvertIpv4Address(unicastAddress.IPv4Mask));
}
}
else
{
Logger.Info?.Print(LogClass.ServiceLdn, $"Console's LDN IP is \"{unicastAddress.Address}\".");
Logger.Info?.Print(LogClass.ServiceLdn, $"LDN obtained proxy IP.");

context.ResponseData.Write(NetworkHelpers.ConvertIpv4Address(unicastAddress.Address));
context.ResponseData.Write(NetworkHelpers.ConvertIpv4Address(unicastAddress.IPv4Mask));
context.ResponseData.Write(config.ProxyIp);
context.ResponseData.Write(config.ProxySubnetMask);
}
}
else
Expand Down Expand Up @@ -1066,6 +1089,21 @@ public ResultCode InitializeImpl(ServiceCtx context, ulong pid, int nifmRequestI

switch (mode)
{
case MultiplayerMode.LdnRyu:
try
{
if (!IPAddress.TryParse(LanPlayHost, out IPAddress ipAddress))
{
ipAddress = Dns.GetHostEntry(LanPlayHost).AddressList[0];
}
NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), LanPlayPort, context.Device.Configuration);
}
catch (Exception)
{
Logger.Error?.Print(LogClass.ServiceLdn, "Could not locate LdnRyu server. Defaulting to stubbed wireless.");
NetworkClient = new LdnDisabledClient();
}
break;
case MultiplayerMode.LdnMitm:
NetworkClient = new LdnMitmClient(context.Device.Configuration);
break;
Expand Down Expand Up @@ -1103,7 +1141,7 @@ public void Dispose()
_accessPoint?.Dispose();
_accessPoint = null;

NetworkClient?.Dispose();
NetworkClient?.DisconnectAndStop();
NetworkClient = null;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Ldn.Types;
using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.Types;
using System;
Expand All @@ -6,33 +7,38 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
{
class LdnDisabledClient : INetworkClient
{
public ProxyConfig Config { get; }
public bool NeedsRealId => true;

public event EventHandler<NetworkChangeEventArgs> NetworkChange;

public NetworkError Connect(ConnectRequest request)
{
Logger.Warning?.PrintMsg(LogClass.ServiceLdn, "Attempted to connect to a network, but Multiplayer is disabled!");
NetworkChange?.Invoke(this, new NetworkChangeEventArgs(new NetworkInfo(), false));

return NetworkError.None;
}

public NetworkError ConnectPrivate(ConnectPrivateRequest request)
{
Logger.Warning?.PrintMsg(LogClass.ServiceLdn, "Attempted to connect to a network, but Multiplayer is disabled!");
NetworkChange?.Invoke(this, new NetworkChangeEventArgs(new NetworkInfo(), false));

return NetworkError.None;
}

public bool CreateNetwork(CreateAccessPointRequest request, byte[] advertiseData)
{
Logger.Warning?.PrintMsg(LogClass.ServiceLdn, "Attempted to create a network, but Multiplayer is disabled!");
NetworkChange?.Invoke(this, new NetworkChangeEventArgs(new NetworkInfo(), false));

return true;
}

public bool CreateNetworkPrivate(CreateAccessPointPrivateRequest request, byte[] advertiseData)
{
Logger.Warning?.PrintMsg(LogClass.ServiceLdn, "Attempted to create a network, but Multiplayer is disabled!");
NetworkChange?.Invoke(this, new NetworkChangeEventArgs(new NetworkInfo(), false));

return true;
Expand All @@ -49,6 +55,7 @@ public ResultCode Reject(DisconnectReason disconnectReason, uint nodeId)

public NetworkInfo[] Scan(ushort channel, ScanFilter scanFilter)
{
Logger.Warning?.PrintMsg(LogClass.ServiceLdn, "Attempted to scan for networks, but Multiplayer is disabled!");
return Array.Empty<NetworkInfo>();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
/// </summary>
internal class LdnMitmClient : INetworkClient
{
public ProxyConfig Config { get; }
public bool NeedsRealId => false;

public event EventHandler<NetworkChangeEventArgs> NetworkChange;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu
{
interface IProxyClient
{
bool SendAsync(byte[] buffer);
}
}
Loading