mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-06-27 06:39:06 +00:00
Enables full trimming for Ryujinx, and in doing so removes many usages of reflection, namely: IUserService no longer uses reflection to find possible service types, and now has a generated switch based on name Ryujinx.HLE.HOS.Tamper no longer uses dynamic to do operations, now using INumber<T> and friends Cmif and Tipc commands in Ryujinx.HLE.HOS.Services no longer get resolved via reflection and are now done via generated virtual methods Fix things broken by trimming (profile panel, DiscordRPC)
207 lines
7.6 KiB
C#
207 lines
7.6 KiB
C#
using Ryujinx.Common;
|
|
using Ryujinx.Common.Configuration;
|
|
using Ryujinx.Common.Logging;
|
|
using Ryujinx.Common.Utilities;
|
|
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService;
|
|
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types;
|
|
using System;
|
|
using System.Net.NetworkInformation;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
|
{
|
|
partial class IGeneralService : DisposableIpcService
|
|
{
|
|
private readonly GeneralServiceDetail _generalServiceDetail;
|
|
|
|
private IPInterfaceProperties _targetPropertiesCache = null;
|
|
private UnicastIPAddressInformation _targetAddressInfoCache = null;
|
|
private string _cacheChosenInterface = null;
|
|
|
|
public IGeneralService(ServiceCtx context)
|
|
{
|
|
_generalServiceDetail = new GeneralServiceDetail
|
|
{
|
|
ClientId = GeneralServiceManager.Count,
|
|
IsAnyInternetRequestAccepted = !context.Device.DirtyHacks.IsEnabled(DirtyHack.NifmServiceDisableIsAnyInternetRequestAccepted), // NOTE: Why not accept any internet request?
|
|
};
|
|
|
|
NetworkChange.NetworkAddressChanged += LocalInterfaceCacheHandler;
|
|
|
|
GeneralServiceManager.Add(_generalServiceDetail);
|
|
}
|
|
|
|
[CommandCmif(1)]
|
|
// GetClientId() -> buffer<nn::nifm::ClientId, 0x1a, 4>
|
|
public ResultCode GetClientId(ServiceCtx context)
|
|
{
|
|
ulong position = context.Request.RecvListBuff[0].Position;
|
|
|
|
context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize(sizeof(int));
|
|
|
|
context.Memory.Write(position, _generalServiceDetail.ClientId);
|
|
|
|
return ResultCode.Success;
|
|
}
|
|
|
|
[CommandCmif(4)]
|
|
// CreateRequest(u32 version) -> object<nn::nifm::detail::IRequest>
|
|
public ResultCode CreateRequest(ServiceCtx context)
|
|
{
|
|
uint version = context.RequestData.ReadUInt32();
|
|
|
|
MakeObject(context, new IRequest(context.Device.System, version));
|
|
|
|
// Doesn't occur in our case.
|
|
// return ResultCode.ObjectIsNull;
|
|
|
|
Logger.Stub?.PrintStub(LogClass.ServiceNifm, new { version });
|
|
|
|
return ResultCode.Success;
|
|
}
|
|
|
|
[CommandCmif(5)]
|
|
// GetCurrentNetworkProfile() -> buffer<nn::nifm::detail::sf::NetworkProfileData, 0x1a, 0x17c>
|
|
public ResultCode GetCurrentNetworkProfile(ServiceCtx context)
|
|
{
|
|
ulong networkProfileDataPosition = context.Request.RecvListBuff[0].Position;
|
|
|
|
(IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastAddress) = GetLocalInterface(context);
|
|
|
|
if (interfaceProperties == null || unicastAddress == null)
|
|
{
|
|
return ResultCode.NoInternetConnection;
|
|
}
|
|
|
|
Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
|
|
|
|
context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize((uint)Unsafe.SizeOf<NetworkProfileData>());
|
|
|
|
NetworkProfileData networkProfile = new()
|
|
{
|
|
Uuid = Random.Shared.NextUInt128(),
|
|
};
|
|
|
|
networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
|
|
networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties);
|
|
|
|
"RyujinxNetwork"u8.CopyTo(networkProfile.Name.AsSpan());
|
|
|
|
context.Memory.Write(networkProfileDataPosition, networkProfile);
|
|
|
|
return ResultCode.Success;
|
|
}
|
|
|
|
[CommandCmif(12)]
|
|
// GetCurrentIpAddress() -> nn::nifm::IpV4Address
|
|
public ResultCode GetCurrentIpAddress(ServiceCtx context)
|
|
{
|
|
(_, UnicastIPAddressInformation unicastAddress) = GetLocalInterface(context);
|
|
|
|
if (unicastAddress == null)
|
|
{
|
|
return ResultCode.NoInternetConnection;
|
|
}
|
|
|
|
context.ResponseData.WriteStruct(new IpV4Address(unicastAddress.Address));
|
|
|
|
Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
|
|
|
|
return ResultCode.Success;
|
|
}
|
|
|
|
[CommandCmif(15)]
|
|
// GetCurrentIpConfigInfo() -> (nn::nifm::IpAddressSetting, nn::nifm::DnsSetting)
|
|
public ResultCode GetCurrentIpConfigInfo(ServiceCtx context)
|
|
{
|
|
(IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastAddress) = GetLocalInterface(context);
|
|
|
|
if (interfaceProperties == null || unicastAddress == null)
|
|
{
|
|
return ResultCode.NoInternetConnection;
|
|
}
|
|
|
|
Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
|
|
|
|
context.ResponseData.WriteStruct(new IpAddressSetting(interfaceProperties, unicastAddress));
|
|
context.ResponseData.WriteStruct(new DnsSetting(interfaceProperties));
|
|
|
|
return ResultCode.Success;
|
|
}
|
|
|
|
[CommandCmif(18)]
|
|
// GetInternetConnectionStatus() -> nn::nifm::detail::sf::InternetConnectionStatus
|
|
public ResultCode GetInternetConnectionStatus(ServiceCtx context)
|
|
{
|
|
if (!NetworkInterface.GetIsNetworkAvailable())
|
|
{
|
|
return ResultCode.NoInternetConnection;
|
|
}
|
|
|
|
InternetConnectionStatus internetConnectionStatus = new()
|
|
{
|
|
Type = InternetConnectionType.WiFi,
|
|
WifiStrength = 3,
|
|
State = InternetConnectionState.Connected,
|
|
};
|
|
|
|
context.ResponseData.WriteStruct(internetConnectionStatus);
|
|
|
|
return ResultCode.Success;
|
|
}
|
|
|
|
[CommandCmif(21)]
|
|
// IsAnyInternetRequestAccepted(buffer<nn::nifm::ClientId, 0x19, 4>) -> bool
|
|
public ResultCode IsAnyInternetRequestAccepted(ServiceCtx context)
|
|
{
|
|
ulong position = context.Request.PtrBuff[0].Position;
|
|
#pragma warning disable IDE0059 // Remove unnecessary value assignment
|
|
ulong size = context.Request.PtrBuff[0].Size;
|
|
#pragma warning restore IDE0059
|
|
|
|
int clientId = context.Memory.Read<int>(position);
|
|
|
|
context.ResponseData.Write(GeneralServiceManager.Get(clientId).IsAnyInternetRequestAccepted);
|
|
|
|
return ResultCode.Success;
|
|
}
|
|
|
|
private (IPInterfaceProperties, UnicastIPAddressInformation) GetLocalInterface(ServiceCtx context)
|
|
{
|
|
if (!NetworkInterface.GetIsNetworkAvailable())
|
|
{
|
|
return (null, null);
|
|
}
|
|
|
|
string chosenInterface = context.Device.Configuration.MultiplayerLanInterfaceId;
|
|
|
|
if (_targetPropertiesCache == null || _targetAddressInfoCache == null || _cacheChosenInterface != chosenInterface)
|
|
{
|
|
_cacheChosenInterface = chosenInterface;
|
|
|
|
(_targetPropertiesCache, _targetAddressInfoCache) = NetworkHelpers.GetLocalInterface(chosenInterface);
|
|
}
|
|
|
|
return (_targetPropertiesCache, _targetAddressInfoCache);
|
|
}
|
|
|
|
private void LocalInterfaceCacheHandler(object sender, EventArgs e)
|
|
{
|
|
Logger.Info?.Print(LogClass.ServiceNifm, "NetworkAddress changed, invalidating cached data.");
|
|
|
|
_targetPropertiesCache = null;
|
|
_targetAddressInfoCache = null;
|
|
}
|
|
|
|
protected override void Dispose(bool isDisposing)
|
|
{
|
|
if (isDisposing)
|
|
{
|
|
NetworkChange.NetworkAddressChanged -= LocalInterfaceCacheHandler;
|
|
|
|
GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
|
|
}
|
|
}
|
|
}
|
|
}
|