IGeneralService.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. using Ryujinx.Common;
  2. using Ryujinx.Common.Logging;
  3. using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService;
  4. using Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types;
  5. using Ryujinx.HLE.Utilities;
  6. using System;
  7. using System.Net.NetworkInformation;
  8. using System.Runtime.CompilerServices;
  9. using System.Text;
  10. namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
  11. {
  12. class IGeneralService : DisposableIpcService
  13. {
  14. private GeneralServiceDetail _generalServiceDetail;
  15. public IGeneralService()
  16. {
  17. _generalServiceDetail = new GeneralServiceDetail
  18. {
  19. ClientId = GeneralServiceManager.Count,
  20. IsAnyInternetRequestAccepted = true // NOTE: Why not accept any internet request?
  21. };
  22. GeneralServiceManager.Add(_generalServiceDetail);
  23. }
  24. [CommandHipc(1)]
  25. // GetClientId() -> buffer<nn::nifm::ClientId, 0x1a, 4>
  26. public ResultCode GetClientId(ServiceCtx context)
  27. {
  28. ulong position = context.Request.RecvListBuff[0].Position;
  29. context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize(sizeof(int));
  30. context.Memory.Write(position, _generalServiceDetail.ClientId);
  31. return ResultCode.Success;
  32. }
  33. [CommandHipc(4)]
  34. // CreateRequest(u32 version) -> object<nn::nifm::detail::IRequest>
  35. public ResultCode CreateRequest(ServiceCtx context)
  36. {
  37. uint version = context.RequestData.ReadUInt32();
  38. MakeObject(context, new IRequest(context.Device.System, version));
  39. // Doesn't occur in our case.
  40. // return ResultCode.ObjectIsNull;
  41. Logger.Stub?.PrintStub(LogClass.ServiceNifm, new { version });
  42. return ResultCode.Success;
  43. }
  44. [CommandHipc(5)]
  45. // GetCurrentNetworkProfile() -> buffer<nn::nifm::detail::sf::NetworkProfileData, 0x1a, 0x17c>
  46. public ResultCode GetCurrentNetworkProfile(ServiceCtx context)
  47. {
  48. ulong networkProfileDataPosition = context.Request.RecvListBuff[0].Position;
  49. (IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastAddress) = GetLocalInterface();
  50. if (interfaceProperties == null || unicastAddress == null)
  51. {
  52. return ResultCode.NoInternetConnection;
  53. }
  54. Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
  55. context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize((uint)Unsafe.SizeOf<NetworkProfileData>());
  56. NetworkProfileData networkProfile = new NetworkProfileData
  57. {
  58. Uuid = new UInt128(Guid.NewGuid().ToByteArray())
  59. };
  60. networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
  61. networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties);
  62. Encoding.ASCII.GetBytes("RyujinxNetwork").CopyTo(networkProfile.Name.ToSpan());
  63. context.Memory.Write(networkProfileDataPosition, networkProfile);
  64. return ResultCode.Success;
  65. }
  66. [CommandHipc(12)]
  67. // GetCurrentIpAddress() -> nn::nifm::IpV4Address
  68. public ResultCode GetCurrentIpAddress(ServiceCtx context)
  69. {
  70. (_, UnicastIPAddressInformation unicastAddress) = GetLocalInterface();
  71. if (unicastAddress == null)
  72. {
  73. return ResultCode.NoInternetConnection;
  74. }
  75. context.ResponseData.WriteStruct(new IpV4Address(unicastAddress.Address));
  76. Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
  77. return ResultCode.Success;
  78. }
  79. [CommandHipc(15)]
  80. // GetCurrentIpConfigInfo() -> (nn::nifm::IpAddressSetting, nn::nifm::DnsSetting)
  81. public ResultCode GetCurrentIpConfigInfo(ServiceCtx context)
  82. {
  83. (IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastAddress) = GetLocalInterface();
  84. if (interfaceProperties == null || unicastAddress == null)
  85. {
  86. return ResultCode.NoInternetConnection;
  87. }
  88. Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
  89. context.ResponseData.WriteStruct(new IpAddressSetting(interfaceProperties, unicastAddress));
  90. context.ResponseData.WriteStruct(new DnsSetting(interfaceProperties));
  91. return ResultCode.Success;
  92. }
  93. [CommandHipc(18)]
  94. // GetInternetConnectionStatus() -> nn::nifm::detail::sf::InternetConnectionStatus
  95. public ResultCode GetInternetConnectionStatus(ServiceCtx context)
  96. {
  97. if (!NetworkInterface.GetIsNetworkAvailable())
  98. {
  99. return ResultCode.NoInternetConnection;
  100. }
  101. InternetConnectionStatus internetConnectionStatus = new InternetConnectionStatus
  102. {
  103. Type = InternetConnectionType.WiFi,
  104. WifiStrength = 3,
  105. State = InternetConnectionState.Connected,
  106. };
  107. context.ResponseData.WriteStruct(internetConnectionStatus);
  108. return ResultCode.Success;
  109. }
  110. [CommandHipc(21)]
  111. // IsAnyInternetRequestAccepted(buffer<nn::nifm::ClientId, 0x19, 4>) -> bool
  112. public ResultCode IsAnyInternetRequestAccepted(ServiceCtx context)
  113. {
  114. ulong position = context.Request.PtrBuff[0].Position;
  115. ulong size = context.Request.PtrBuff[0].Size;
  116. int clientId = context.Memory.Read<int>(position);
  117. context.ResponseData.Write(GeneralServiceManager.Get(clientId).IsAnyInternetRequestAccepted);
  118. return ResultCode.Success;
  119. }
  120. private (IPInterfaceProperties, UnicastIPAddressInformation) GetLocalInterface()
  121. {
  122. if (!NetworkInterface.GetIsNetworkAvailable())
  123. {
  124. return (null, null);
  125. }
  126. IPInterfaceProperties targetProperties = null;
  127. UnicastIPAddressInformation targetAddressInfo = null;
  128. NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
  129. foreach (NetworkInterface adapter in interfaces)
  130. {
  131. // Ignore loopback and non IPv4 capable interface.
  132. if (targetProperties == null && adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback && adapter.Supports(NetworkInterfaceComponent.IPv4))
  133. {
  134. IPInterfaceProperties properties = adapter.GetIPProperties();
  135. if (properties.GatewayAddresses.Count > 0 && properties.DnsAddresses.Count > 0)
  136. {
  137. foreach (UnicastIPAddressInformation info in properties.UnicastAddresses)
  138. {
  139. // Only accept an IPv4 address
  140. if (info.Address.GetAddressBytes().Length == 4)
  141. {
  142. targetProperties = properties;
  143. targetAddressInfo = info;
  144. break;
  145. }
  146. }
  147. }
  148. }
  149. }
  150. return (targetProperties, targetAddressInfo);
  151. }
  152. protected override void Dispose(bool isDisposing)
  153. {
  154. if (isDisposing)
  155. {
  156. GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
  157. }
  158. }
  159. }
  160. }